Skip to content

MCP access part 5: Claude desktop config parser#55179

Merged
greedy52 merged 4 commits intomasterfrom
STeve/54705_claude_config
May 29, 2025
Merged

MCP access part 5: Claude desktop config parser#55179
greedy52 merged 4 commits intomasterfrom
STeve/54705_claude_config

Conversation

@greedy52
Copy link
Copy Markdown
Contributor

@greedy52 greedy52 commented May 27, 2025

Related:

Doing a small separate PR for parser so it can be shared for tsh mcp db

@greedy52 greedy52 requested review from Tener and gabrielcorado May 27, 2025 15:53
@greedy52 greedy52 self-assigned this May 27, 2025
@greedy52 greedy52 added no-changelog Indicates that a PR does not require a changelog entry MCP MCP Server related labels May 27, 2025
@greedy52 greedy52 mentioned this pull request May 16, 2025
14 tasks
Comment thread lib/client/mcp/claude/config.go Outdated
return trace.Wrap(err)
}
var allFields map[string]any
if err := json.Unmarshal(data, &allFields); err != nil {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having a hard time understanding what the 2-phase unmarshal is doing here.

Copy link
Copy Markdown
Contributor Author

@greedy52 greedy52 May 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

once for known fields and once for unknown fields. it's quite awkward to do this in golang. i didn't find a good way to do this.

I will try out json patch

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current code is idiomatic enough, but a comment would be most welcome.

Copy link
Copy Markdown
Contributor Author

@greedy52 greedy52 May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into json patch but it doesn't work very well. as suggested by @Tener , i switched to https://github.com/tidwall/sjson

let me know what you think about the latest changes.

one problem i have with sjson is the formatting so i decided to apply some extra formatting when saving. not sure if i went a little too far. Since this is a config edited by human most of the time, i imagine you want it to be prettified by default.

Copy link
Copy Markdown
Contributor

@juliaogris juliaogris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have probably seen this SO post https://stackoverflow.com/a/33437853

I think my mental model would be to use AdditionalFields, not AllFields, but you might have good reasons for doing this that I don't understand.

Comment thread lib/client/mcp/claude/config_test.go Outdated
Copy link
Copy Markdown
Contributor

@Tener Tener left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted I think we should try very hard to not reformat the config. I suggested one possible solution.

Comment thread lib/client/mcp/claude/config.go Outdated
return trace.Wrap(err)
}
var allFields map[string]any
if err := json.Unmarshal(data, &allFields); err != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current code is idiomatic enough, but a comment would be most welcome.

Comment thread lib/client/mcp/claude/config.go Outdated
Comment thread lib/client/mcp/claude/config.go Outdated
@greedy52 greedy52 requested review from Tener, juliaogris and zmb3 May 28, 2025 20:29
@greedy52 greedy52 force-pushed the STeve/54705_claude_config branch from 53fd7a6 to 295a914 Compare May 28, 2025 20:38
@greedy52 greedy52 force-pushed the STeve/54705_claude_config branch from 295a914 to b413836 Compare May 28, 2025 20:42
Comment thread lib/client/mcp/claude/config.go Outdated
}

// LoadConfig loads the Claude Desktop's config from the provided path.
func LoadConfig(configPath string) (*Config, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion/nit: Place those behind a struct (maybe we can init it with the config path) so we can rely on an interface on the caller side. It would be easier to add and test other configurations.

What I would expect to use from the caller:

type ConfigFormat interface {
    LoadConfig(configPath string) (Config, error)
    
    // Just for generating the config in the specific format.
    EmptyConfig() Config
    // or...
    GenerateConfig(serverName string, server MCPServer) ([]byte, error)
}

type Config interface {
    PutMCPServer() error
    RemoveMCPServer() error
    Save() error
    Generate() ([]byte, error)
}

I know that implies having shared structs for MCPServer. For the initial version, we could provide the necessary functions to generate a minimal configuration (without loading or updating any file).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

caller side can do this if it needs to. also the config and parsing is simple enough so i would probably just write a file in t.Temp() to when testing caller

Comment thread lib/client/mcp/claude/config.go
Comment thread lib/client/mcp/claude/config.go
@public-teleport-github-review-bot public-teleport-github-review-bot Bot removed the request for review from fspmarshall May 29, 2025 08:47
@greedy52 greedy52 added this pull request to the merge queue May 29, 2025
@greedy52 greedy52 removed this pull request from the merge queue due to a manual request May 29, 2025
@greedy52 greedy52 enabled auto-merge May 29, 2025 21:24
@greedy52 greedy52 added this pull request to the merge queue May 29, 2025
Merged via the queue into master with commit 60fe18e May 29, 2025
42 checks passed
@greedy52 greedy52 deleted the STeve/54705_claude_config branch May 29, 2025 22:03
greedy52 added a commit that referenced this pull request Jun 26, 2025
* claude desktop config

* rework

* split Config to Config and FileConfig

* add a comment on unofficial linux
@greedy52 greedy52 mentioned this pull request Jun 26, 2025
github-merge-queue Bot pushed a commit that referenced this pull request Jul 21, 2025
* Initial PostgreSQL MCP support (#54431)

* feat(mcp): initial postgres mcp

* test(postgres): fix missing mock function

* fix(gomod): go mod tidy all

* refactor: code review suggestions

* fix(tsh): mcp init missing logger

* chore(tsh): missing other route to database field

* refactor: use in-memory net listener

* test(tsh): add mcp db command test

* chore: fix license

* refactor(tsh): move logger init

* test(mcp): sort slices to avoid flakiness

* chore: fix lint

* test(mcp): sort the resources before assertion

* fix(mcp): update error handler for better message

* refactor: code review suggestions

* feat: add external error retriever for more accurate error messages

* refactor: use the same logger init for mcp purposes

* refactor: code review suggestions

* refactor(tsh): rename command to `tsh mcp db start`

* refactor(mcp): protect database resources with rw mutex

* chore: update server godocs

* chore: go mod tidy

* refactor: update command to take list of databases

* chore(mcp): license

* chore(tsh): remove unused function

* refactor: code review suggestions

* refactor(tsh): validate duplicated databases in MCP configuration

* refactor(tsh): rename files to mcp_db

* feat(mcp): add cluster name to the database resource

* fix(tsh): update InitLogger return type (#55479)

* MCP access part 1: update app definition and config (#54706)

* MCP access part 1: update app definition and config

* address feedback

* make -C integrations/operator crd

* MCP access part 2: new role options, access checker, role editor (#54734)

* MCP access part 2: new role options, access checker, role editor

* catch unsupported mcp fields

* simplify mcpToolsToModel

* MCP access part 3: audit events and reporting (#54779)

* MCP access part 3: audit events and reporting

* add new icon, storybook, format

* MCP access part 4: mcputils (#54880)

* MCP access part 4: mcp helpers

* address feedback

* address comment, minor edits

* update mcp-go

* MCP access part 5: Claude desktop config parser (#55179)

* claude desktop config

* rework

* split Config to Config and FileConfig

* add a comment on unofficial linux

* MCP access part 6: "tsh mcp ls" (#55292)

* MCP access part 6: "tsh mcp ls"

* address feedback

* MCP access part 7: MCP app in Web UI (#55306)

* MCP access part 7: MCP app in Web UI

* Make spacing in modal closer to what's in database modal

* add mcp app to ResourceActionButton.story.tsx

* move AppSubKind to shared/services/types.

* remove --format claude (not needed see part 8)

* add jsdoc

---------

Co-authored-by: Rafał Cieślak <rafal.cieslak@goteleport.com>

* MCP access part 8: tsh mcp config (#55370)

* MCP access part 8: tsh mcp login/logout

* change to --format and --config-file

* switch to config and drop logout

* enable debug by default

* remove unused ut functions

* MCP access part 9: tsh mcp connect, stub server, integration test (#55547)

* MCP access part 9: tsh mcp connect, stub server, integration test

* fix tests and lint

* MCP access part 10: server handler (#55644)

* MCP access part 10: server handler

* address feedback and fix docker tests

* add more comments

* minor lint fix

* move set logger default after other checks

* Implement `tsh mcp db config` (#55781)

* feat(tsh): add `tsh mcp db config` subcommand

* chore(claude): fix lint

* refactor: code review suggestions

* refactor: code review suggestions

* test(tsh): add missing option on test case

* chore(tsh): add message on manually adding database URI

* Refactor MCP database access to dial ALPN proxy directly (#55836)

* refactor: dial database instead of using local proxy for MCP servers

* refactor: review suggestions

* manual fixes

* tctl users add/update to support mcp tools trait (#56771)

* tctl users add/update to support mcp tools trait

* revert empty slice capability

* Enhances MCP servers usage with Cursor (#56474)

* feat(mcp): enhances MCP servers usage with Cursor

* refactor: code review suggestions

* mcputils refactor and new mcptest package (#56010)

* mcp server and mcputils refactor

* mcptest package

* allow testing in mcptest

* Teleport MCP demo server (#56637)

* Teleport MCP demo server

* replace guide tool with session tool, and switch to resource label

* add new flag to teleport configure

* replace teleport_session_id with mcp_transport_type

* feat(gomod): update mcp-go to v0.32.0

* eslint-disable-next-line (same in master)

---------

Co-authored-by: Gabriel Corado <gabriel.oliveira@goteleport.com>
Co-authored-by: Rafał Cieślak <rafal.cieslak@goteleport.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

MCP MCP Server related no-changelog Indicates that a PR does not require a changelog entry size/md

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants