feat(sdk-runner): expand KNOWN_SDKS to all tier 1 SDKs (#417)
* feat(sdk-runner): expand KNOWN_SDKS to all tier 1 SDKs - go-sdk: point at the relocated conformance/ fixtures (the old examples/server/conformance path is gone on main), add the everything-client fixture that now exists upstream, and wire conformance/baseline.yml as the expected-failures baseline. - python-sdk: new entry for main, which targets the 2026-07-28 revision (same uv workspace layout as the v1.x entry). - csharp-sdk: new entry driving the ConformanceClient / ConformanceServer fixtures via the .NET 10 SDK. The client takes the scenario as argv[0], so the command bridges MCP_CONFORMANCE_SCENARIO into argv; the server exposes the SEP-2575 stateless lifecycle at /stateless. * docs: match the sdk override example's lead-in to its content The example now shows field overrides on a built-in entry rather than a one-off ref, so the introducing sentence shouldn't promise a ref override.
This commit is contained in:
parent
0c85302241
commit
2a705a811e
3 changed files with 89 additions and 11 deletions
11
README.md
11
README.md
|
|
@ -281,13 +281,14 @@ npm start -- sdk typescript-sdk --mode client --spec-version draft
|
|||
|
||||
Build/run commands for each official SDK are looked up by name from [`src/sdk-runner/known-sdks.ts`](src/sdk-runner/known-sdks.ts) — no config file is required in the SDK repo. Resolution order is **CLI flag > built-in entry**, so any field can be overridden on the command line for refs that diverge from the built-in.
|
||||
|
||||
An SDK can have more than one entry when its layout differs across major versions — e.g. `typescript-sdk` (v2, the `main` monorepo) and `typescript-sdk-v1` (the published npm v1.x line). An entry may set `defaultRef` (the branch used when you don't pass `@<ref>`) and `repo` (the real clone target when the entry name is an alias). Overriding for a one-off ref:
|
||||
An SDK can have more than one entry when its layout differs across major versions — e.g. `typescript-sdk` (v2, the `main` monorepo) and `typescript-sdk-v1` (the published npm v1.x line). An entry may set `defaultRef` (the branch used when you don't pass `@<ref>`) and `repo` (the real clone target when the entry name is an alias). Overriding built-in fields for a one-off run:
|
||||
|
||||
```bash
|
||||
npm start -- sdk owner/go-sdk@some-branch \
|
||||
--mode client \
|
||||
--build-cmd 'go build -tags mcp_go_client_oauth -o ./.conformance-client ./conformance/everything-client' \
|
||||
--client-cmd './.conformance-client'
|
||||
# e.g. a 2026-07-28 run against go-sdk's server — the built-in server command
|
||||
# pins -stateless=false (what the dated-spec suites need), so override it to
|
||||
# get the SEP-2575 stateless lifecycle:
|
||||
npm start -- sdk go-sdk --mode server --suite all --spec-version 2026-07-28 \
|
||||
--server-cmd './.conformance-server -http=localhost:3000'
|
||||
```
|
||||
|
||||
To add a new SDK to the matrix, add an entry to `KNOWN_SDKS`.
|
||||
|
|
|
|||
|
|
@ -38,17 +38,44 @@ export const KNOWN_SDKS: Record<string, SdkConfig> = {
|
|||
},
|
||||
expectedFailures: 'test/conformance/conformance-baseline.yml'
|
||||
},
|
||||
// Fixtures live under conformance/ (everything-client + everything-server,
|
||||
// mirroring scripts/{client,server}-conformance.sh). The server's -stateless
|
||||
// flag defaults to true; -stateless=false pins the stateful transport, which
|
||||
// the dated-spec (`active` suite) scenarios need — for a 2026-07-28 /
|
||||
// SEP-2575 run, override with --server-cmd './.conformance-server -http=localhost:3000'
|
||||
// to get the stateless lifecycle.
|
||||
'go-sdk': {
|
||||
build: 'go build -o ./.conformance-server ./examples/server/conformance',
|
||||
// Upstream go-sdk has no client conformance fixture yet (see go-sdk#859).
|
||||
build:
|
||||
'go build -o ./.conformance-server ./conformance/everything-server && go build -o ./.conformance-client ./conformance/everything-client',
|
||||
client: {
|
||||
command: './.conformance-client'
|
||||
},
|
||||
server: {
|
||||
command: './.conformance-server -http=:3000',
|
||||
command: './.conformance-server -http=localhost:3000 -stateless=false',
|
||||
url: 'http://localhost:3000'
|
||||
}
|
||||
},
|
||||
expectedFailures: 'conformance/baseline.yml'
|
||||
},
|
||||
// main — targets the 2026-07-28 revision. Same uv workspace layout as v1.x
|
||||
// (client fixture in .github/actions/conformance/, mcp-everything-server
|
||||
// workspace package). Two baselines exist upstream: expected-failures.yml
|
||||
// covers runs at the latest dated spec (the default here), and
|
||||
// expected-failures.2026-07-28.yml covers --spec-version 2026-07-28 runs —
|
||||
// pass the latter via --expected-failures when targeting the new revision.
|
||||
'python-sdk': {
|
||||
build: 'uv sync --frozen --all-extras --all-packages',
|
||||
client: {
|
||||
command: 'uv run --frozen python .github/actions/conformance/client.py'
|
||||
},
|
||||
server: {
|
||||
command: 'uv run --frozen mcp-everything-server --port 3000',
|
||||
url: 'http://localhost:3000/mcp'
|
||||
},
|
||||
expectedFailures: '.github/actions/conformance/expected-failures.yml'
|
||||
},
|
||||
// v1.x — the stable, published line of the python-sdk, analogous to
|
||||
// typescript-sdk-v1 (v2/main is mid-refactor and noisy). Clones the
|
||||
// python-sdk repo, defaulting to the `v1.x` branch, and targets the latest
|
||||
// typescript-sdk-v1. Clones the python-sdk repo, defaulting to the `v1.x`
|
||||
// branch, and targets the latest
|
||||
// dated spec so draft-only scenarios/checks are excluded by default. uv
|
||||
// workspace: the `mcp` (client) and `mcp-everything-server` (server) packages
|
||||
// are both members, so one `uv sync --all-packages` covers both modes.
|
||||
|
|
@ -68,6 +95,27 @@ export const KNOWN_SDKS: Record<string, SdkConfig> = {
|
|||
url: 'http://localhost:3000/mcp'
|
||||
},
|
||||
expectedFailures: '.github/actions/conformance/expected-failures.yml'
|
||||
},
|
||||
// Fixtures live in tests/ModelContextProtocol.ConformanceClient and
|
||||
// tests/ModelContextProtocol.ConformanceServer (requires the .NET 10 SDK,
|
||||
// per global.json); build output goes to the repo-level artifacts/ tree
|
||||
// (UseArtifactsOutput), not per-project bin/. The client binary takes the scenario as its first
|
||||
// argument rather than reading MCP_CONFORMANCE_SCENARIO, so the command
|
||||
// bridges the env var into argv ($1 is the server URL the harness appends).
|
||||
// The server serves the stateful lifecycle at / and the SEP-2575 stateless
|
||||
// lifecycle at /stateless from the same port — for a 2026-07-28 run,
|
||||
// override with --server-url http://localhost:3000/stateless.
|
||||
'csharp-sdk': {
|
||||
build:
|
||||
'dotnet build tests/ModelContextProtocol.ConformanceClient -c Release -f net10.0 && dotnet build tests/ModelContextProtocol.ConformanceServer -c Release -f net10.0',
|
||||
client: {
|
||||
command: `bash -c 'exec dotnet artifacts/bin/ModelContextProtocol.ConformanceClient/Release/net10.0/ModelContextProtocol.ConformanceClient.dll "$MCP_CONFORMANCE_SCENARIO" "$1"' conformance-client`
|
||||
},
|
||||
server: {
|
||||
command:
|
||||
'dotnet artifacts/bin/ModelContextProtocol.ConformanceServer/Release/net10.0/ModelContextProtocol.ConformanceServer.dll --urls http://localhost:3000',
|
||||
url: 'http://localhost:3000'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,35 @@ describe('lookupBuiltinConfig', () => {
|
|||
expect(lookupBuiltinConfig('typescript-sdk')?.specVersion).toBeUndefined();
|
||||
});
|
||||
|
||||
it('go-sdk exposes both fixtures from conformance/ and a baseline', () => {
|
||||
const go = lookupBuiltinConfig('go-sdk');
|
||||
expect(go?.build).toContain('./conformance/everything-server');
|
||||
expect(go?.build).toContain('./conformance/everything-client');
|
||||
expect(go?.client?.command).toBe('./.conformance-client');
|
||||
expect(go?.server?.url).toBe('http://localhost:3000');
|
||||
expect(go?.expectedFailures).toBe('conformance/baseline.yml');
|
||||
});
|
||||
|
||||
it('exposes python-sdk (main) with both commands and no ref/spec pin', () => {
|
||||
const py = lookupBuiltinConfig('python-sdk');
|
||||
expect(py?.repo).toBeUndefined();
|
||||
expect(py?.defaultRef).toBeUndefined();
|
||||
expect(py?.specVersion).toBeUndefined();
|
||||
expect(py?.client?.command).toContain('client.py');
|
||||
expect(py?.server?.command).toContain('mcp-everything-server');
|
||||
expect(py?.server?.url).toBe('http://localhost:3000/mcp');
|
||||
});
|
||||
|
||||
it('exposes csharp-sdk with dotnet fixtures and the scenario-argv bridge', () => {
|
||||
const cs = lookupBuiltinConfig('csharp-sdk');
|
||||
expect(cs?.build).toContain('ModelContextProtocol.ConformanceClient');
|
||||
expect(cs?.build).toContain('ModelContextProtocol.ConformanceServer');
|
||||
// The C# client takes the scenario as argv[0]; the command bridges the
|
||||
// MCP_CONFORMANCE_SCENARIO env var into it.
|
||||
expect(cs?.client?.command).toContain('$MCP_CONFORMANCE_SCENARIO');
|
||||
expect(cs?.server?.url).toBe('http://localhost:3000');
|
||||
});
|
||||
|
||||
it('every built-in entry validates against SdkConfigSchema', () => {
|
||||
for (const [name, cfg] of Object.entries(KNOWN_SDKS)) {
|
||||
expect(() => SdkConfigSchema.parse(cfg), name).not.toThrow();
|
||||
|
|
|
|||
Loading…
Reference in a new issue