@frontmcp/skills 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/catalog/TEMPLATE.md +16 -11
  2. package/catalog/frontmcp-authorities/SKILL.md +116 -11
  3. package/catalog/frontmcp-authorities/references/authority-profiles.md +39 -36
  4. package/catalog/frontmcp-authorities/references/claims-mapping.md +7 -0
  5. package/catalog/frontmcp-authorities/references/custom-evaluators.md +63 -14
  6. package/catalog/frontmcp-channels/SKILL.md +36 -0
  7. package/catalog/frontmcp-channels/examples/channel-sources/file-watcher.md +8 -2
  8. package/catalog/frontmcp-channels/examples/channel-sources/replay-buffer.md +111 -30
  9. package/catalog/frontmcp-channels/examples/channel-two-way/whatsapp-bridge.md +45 -3
  10. package/catalog/frontmcp-channels/references/channel-sources.md +11 -3
  11. package/catalog/frontmcp-channels/references/channel-two-way.md +60 -89
  12. package/catalog/frontmcp-config/SKILL.md +111 -8
  13. package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +4 -4
  14. package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +7 -1
  15. package/catalog/frontmcp-config/examples/configure-deployment-targets/distributed-ha-config.md +1 -1
  16. package/catalog/frontmcp-config/examples/configure-deployment-targets/json-schema-ide-support.md +1 -1
  17. package/catalog/frontmcp-config/examples/configure-deployment-targets/multi-target-with-security.md +12 -9
  18. package/catalog/frontmcp-config/examples/configure-http/cors-restricted-origins.md +2 -2
  19. package/catalog/frontmcp-config/examples/configure-http/entry-path-reverse-proxy.md +1 -1
  20. package/catalog/frontmcp-config/examples/configure-security-headers/csp-report-only.md +1 -1
  21. package/catalog/frontmcp-config/examples/configure-security-headers/full-production-headers.md +1 -1
  22. package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-basic.md +76 -0
  23. package/catalog/frontmcp-config/examples/configure-skills-http/audit-log-redis.md +116 -0
  24. package/catalog/frontmcp-config/examples/configure-skills-http/inject-instructions.md +59 -0
  25. package/catalog/frontmcp-config/references/configure-auth-modes.md +5 -5
  26. package/catalog/frontmcp-config/references/configure-deployment-targets.md +27 -24
  27. package/catalog/frontmcp-config/references/configure-http.md +14 -10
  28. package/catalog/frontmcp-config/references/configure-security-headers.md +2 -2
  29. package/catalog/frontmcp-config/references/configure-session.md +25 -25
  30. package/catalog/frontmcp-config/references/configure-skills-http.md +157 -0
  31. package/catalog/frontmcp-config/references/configure-throttle.md +1 -1
  32. package/catalog/frontmcp-config/references/configure-transport.md +2 -2
  33. package/catalog/frontmcp-deployment/SKILL.md +112 -9
  34. package/catalog/frontmcp-deployment/examples/build-for-browser/browser-build-with-custom-entry.md +23 -11
  35. package/catalog/frontmcp-deployment/examples/build-for-browser/browser-crypto-and-storage.md +44 -17
  36. package/catalog/frontmcp-deployment/examples/build-for-browser/react-provider-setup.md +53 -21
  37. package/catalog/frontmcp-deployment/examples/build-for-cli/cli-binary-build.md +1 -1
  38. package/catalog/frontmcp-deployment/examples/build-for-cli/unix-socket-daemon.md +1 -1
  39. package/catalog/frontmcp-deployment/examples/build-for-mcpb/mcpb-bundle-build.md +1 -1
  40. package/catalog/frontmcp-deployment/examples/build-for-sdk/connect-openai.md +1 -1
  41. package/catalog/frontmcp-deployment/examples/build-for-sdk/multi-platform-connect.md +1 -1
  42. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/basic-worker-deploy.md +7 -8
  43. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-custom-domain.md +8 -6
  44. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-with-kv-storage.md +5 -4
  45. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/cdk-deployment.md +8 -5
  46. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/lambda-handler-with-cors.md +20 -18
  47. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/sam-template-basic.md +8 -5
  48. package/catalog/frontmcp-deployment/examples/deploy-to-node/docker-compose-with-redis.md +3 -3
  49. package/catalog/frontmcp-deployment/examples/deploy-to-node/pm2-with-nginx.md +1 -1
  50. package/catalog/frontmcp-deployment/examples/deploy-to-node/resource-limits.md +2 -2
  51. package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/basic-multistage-dockerfile.md +2 -2
  52. package/catalog/frontmcp-deployment/examples/deploy-to-node-dockerfile/secure-nonroot-dockerfile.md +1 -1
  53. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-mcp-endpoint-test.md +23 -21
  54. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +25 -22
  55. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-skills-cache.md +23 -30
  56. package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/minimal-vercel-config.md +52 -28
  57. package/catalog/frontmcp-deployment/examples/deploy-to-vercel-config/vercel-config-with-security-headers.md +32 -55
  58. package/catalog/frontmcp-deployment/examples/mcp-client-integration/http-remote.md +9 -0
  59. package/catalog/frontmcp-deployment/references/build-for-browser.md +40 -17
  60. package/catalog/frontmcp-deployment/references/build-for-cli.md +8 -8
  61. package/catalog/frontmcp-deployment/references/deploy-to-cloudflare.md +43 -24
  62. package/catalog/frontmcp-deployment/references/deploy-to-lambda.md +36 -25
  63. package/catalog/frontmcp-deployment/references/deploy-to-node-dockerfile.md +56 -14
  64. package/catalog/frontmcp-deployment/references/deploy-to-node.md +9 -6
  65. package/catalog/frontmcp-deployment/references/deploy-to-vercel-config.md +57 -58
  66. package/catalog/frontmcp-deployment/references/deploy-to-vercel.md +49 -59
  67. package/catalog/frontmcp-deployment/references/mcp-client-integration.md +2 -0
  68. package/catalog/frontmcp-development/SKILL.md +186 -11
  69. package/catalog/frontmcp-development/examples/create-agent/custom-multi-pass-agent.md +1 -1
  70. package/catalog/frontmcp-development/examples/create-agent/nested-agents-with-swarm.md +30 -27
  71. package/catalog/frontmcp-development/examples/create-job/job-with-permissions.md +13 -8
  72. package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +33 -23
  73. package/catalog/frontmcp-development/examples/create-provider/config-and-api-providers.md +19 -10
  74. package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +3 -3
  75. package/catalog/frontmcp-development/examples/create-workflow/webhook-triggered-workflow.md +6 -4
  76. package/catalog/frontmcp-development/examples/decorators-guide/agent-skill-job-workflow.md +1 -1
  77. package/catalog/frontmcp-development/examples/decorators-guide/basic-server-with-app-and-tools.md +13 -8
  78. package/catalog/frontmcp-development/examples/decorators-guide/multi-app-with-plugins-and-providers.md +50 -23
  79. package/catalog/frontmcp-development/references/create-agent.md +47 -30
  80. package/catalog/frontmcp-development/references/create-job.md +69 -54
  81. package/catalog/frontmcp-development/references/create-plugin-hooks.md +45 -28
  82. package/catalog/frontmcp-development/references/create-plugin.md +10 -8
  83. package/catalog/frontmcp-development/references/create-prompt.md +3 -3
  84. package/catalog/frontmcp-development/references/create-provider.md +91 -51
  85. package/catalog/frontmcp-development/references/create-resource.md +3 -3
  86. package/catalog/frontmcp-development/references/create-skill.md +2 -2
  87. package/catalog/frontmcp-development/references/create-tool.md +7 -7
  88. package/catalog/frontmcp-development/references/create-workflow.md +8 -10
  89. package/catalog/frontmcp-development/references/decorators-guide.md +92 -56
  90. package/catalog/frontmcp-development/references/official-plugins.md +4 -3
  91. package/catalog/frontmcp-development/references/openapi-adapter.md +1 -1
  92. package/catalog/frontmcp-extensibility/SKILL.md +70 -10
  93. package/catalog/frontmcp-extensibility/examples/skill-audit-log/custom-store.md +197 -0
  94. package/catalog/frontmcp-extensibility/examples/skill-audit-log/verify-chain.md +68 -0
  95. package/catalog/frontmcp-extensibility/examples/vectoriadb/product-catalog-search.md +3 -5
  96. package/catalog/frontmcp-extensibility/examples/vectoriadb/semantic-search-with-persistence.md +4 -11
  97. package/catalog/frontmcp-extensibility/examples/vectoriadb/tfidf-keyword-search.md +41 -30
  98. package/catalog/frontmcp-extensibility/references/skill-audit-log.md +233 -0
  99. package/catalog/frontmcp-extensibility/references/vectoriadb.md +73 -63
  100. package/catalog/frontmcp-guides/SKILL.md +84 -27
  101. package/catalog/frontmcp-guides/examples/example-knowledge-base/agent-and-plugin.md +72 -62
  102. package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md +32 -43
  103. package/catalog/frontmcp-guides/examples/example-task-manager/auth-and-crud-tools.md +24 -17
  104. package/catalog/frontmcp-guides/examples/example-task-manager/authenticated-e2e-tests.md +23 -21
  105. package/catalog/frontmcp-guides/examples/example-task-manager/redis-provider-with-di.md +47 -39
  106. package/catalog/frontmcp-guides/examples/example-weather-api/server-and-app-setup.md +16 -6
  107. package/catalog/frontmcp-guides/examples/example-weather-api/unit-and-e2e-tests.md +9 -8
  108. package/catalog/frontmcp-guides/references/example-knowledge-base.md +192 -265
  109. package/catalog/frontmcp-guides/references/example-task-manager.md +60 -54
  110. package/catalog/frontmcp-guides/references/example-weather-api.md +22 -24
  111. package/catalog/frontmcp-observability/SKILL.md +66 -2
  112. package/catalog/frontmcp-observability/examples/telemetry-api/skill-counters.md +100 -0
  113. package/catalog/frontmcp-observability/examples/tracing-setup/production-tracing.md +7 -2
  114. package/catalog/frontmcp-observability/examples/vendor-integrations/coralogix-setup.md +6 -2
  115. package/catalog/frontmcp-observability/references/telemetry-api.md +72 -8
  116. package/catalog/frontmcp-observability/references/testing-observability.md +33 -49
  117. package/catalog/frontmcp-observability/references/tracing-setup.md +12 -5
  118. package/catalog/frontmcp-observability/references/vendor-integrations.md +46 -1
  119. package/catalog/frontmcp-production-readiness/SKILL.md +134 -3
  120. package/catalog/frontmcp-production-readiness/examples/common-checklist/caching-and-performance.md +57 -36
  121. package/catalog/frontmcp-production-readiness/examples/common-checklist/observability-setup.md +1 -1
  122. package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +102 -6
  123. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/daemon-socket-config.md +2 -1
  124. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/graceful-shutdown-cleanup.md +66 -58
  125. package/catalog/frontmcp-production-readiness/examples/production-cli-daemon/security-and-permissions.md +5 -3
  126. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/durable-objects-state.md +2 -1
  127. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/wrangler-config.md +55 -76
  128. package/catalog/frontmcp-production-readiness/examples/production-lambda/cold-start-connection-reuse.md +43 -40
  129. package/catalog/frontmcp-production-readiness/examples/production-lambda/sam-template.md +63 -94
  130. package/catalog/frontmcp-production-readiness/examples/production-lambda/scaling-and-monitoring.md +28 -18
  131. package/catalog/frontmcp-production-readiness/examples/production-node-sdk/multi-instance-cleanup.md +29 -14
  132. package/catalog/frontmcp-production-readiness/examples/production-node-server/graceful-shutdown.md +58 -42
  133. package/catalog/frontmcp-production-readiness/examples/production-node-server/redis-session-scaling.md +5 -2
  134. package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md +41 -24
  135. package/catalog/frontmcp-production-readiness/examples/production-vercel/vercel-edge-config.md +56 -65
  136. package/catalog/frontmcp-production-readiness/references/common-checklist.md +17 -5
  137. package/catalog/frontmcp-production-readiness/references/production-cli-daemon.md +5 -5
  138. package/catalog/frontmcp-production-readiness/references/production-cloudflare.md +5 -5
  139. package/catalog/frontmcp-production-readiness/references/production-lambda.md +5 -5
  140. package/catalog/frontmcp-production-readiness/references/production-node-sdk.md +5 -5
  141. package/catalog/frontmcp-production-readiness/references/production-node-server.md +1 -1
  142. package/catalog/frontmcp-production-readiness/references/production-vercel.md +5 -5
  143. package/catalog/frontmcp-setup/SKILL.md +88 -0
  144. package/catalog/frontmcp-setup/examples/project-structure-nx/nx-workspace-with-apps.md +10 -4
  145. package/catalog/frontmcp-setup/examples/project-structure-standalone/dev-workflow-commands.md +21 -8
  146. package/catalog/frontmcp-setup/examples/readme-guide/node-server-readme.md +3 -3
  147. package/catalog/frontmcp-setup/references/multi-app-composition.md +4 -3
  148. package/catalog/frontmcp-setup/references/project-structure-nx.md +15 -6
  149. package/catalog/frontmcp-setup/references/project-structure-standalone.md +18 -15
  150. package/catalog/frontmcp-setup/references/readme-guide.md +1 -1
  151. package/catalog/frontmcp-setup/references/setup-project.md +19 -5
  152. package/catalog/frontmcp-setup/references/setup-redis.md +27 -39
  153. package/catalog/frontmcp-setup/references/setup-sqlite.md +25 -18
  154. package/catalog/frontmcp-testing/SKILL.md +102 -15
  155. package/catalog/frontmcp-testing/examples/setup-testing/unit-test-tool-resource-prompt.md +3 -3
  156. package/catalog/frontmcp-testing/examples/test-auth/oauth-flow-test.md +50 -39
  157. package/catalog/frontmcp-testing/examples/test-auth/role-based-access-test.md +52 -29
  158. package/catalog/frontmcp-testing/examples/test-auth/token-factory-test.md +37 -20
  159. package/catalog/frontmcp-testing/examples/test-direct-client/basic-create-test.md +25 -15
  160. package/catalog/frontmcp-testing/examples/test-direct-client/openai-claude-format-test.md +27 -21
  161. package/catalog/frontmcp-testing/examples/test-e2e-handler/basic-e2e-test.md +29 -20
  162. package/catalog/frontmcp-testing/examples/test-e2e-handler/manual-client-with-transport.md +5 -3
  163. package/catalog/frontmcp-testing/examples/test-e2e-handler/tool-call-and-error-e2e.md +35 -26
  164. package/catalog/frontmcp-testing/examples/test-tool-unit/basic-tool-test.md +8 -3
  165. package/catalog/frontmcp-testing/examples/test-tool-unit/schema-validation-test.md +4 -1
  166. package/catalog/frontmcp-testing/examples/test-tool-unit/tool-error-handling-test.md +6 -3
  167. package/catalog/frontmcp-testing/references/setup-testing.md +35 -39
  168. package/catalog/frontmcp-testing/references/test-auth.md +86 -43
  169. package/catalog/frontmcp-testing/references/test-browser-build.md +1 -1
  170. package/catalog/frontmcp-testing/references/test-direct-client.md +29 -19
  171. package/catalog/frontmcp-testing/references/test-e2e-handler.md +31 -19
  172. package/catalog/frontmcp-testing/references/test-tool-unit.md +6 -2
  173. package/catalog/skills-manifest.json +428 -339
  174. package/package.json +1 -1
  175. package/src/manifest.d.ts +13 -0
  176. package/src/manifest.js.map +1 -1
@@ -5,16 +5,26 @@ description: Test authenticated MCP servers with TestTokenFactory, MockOAuthServ
5
5
 
6
6
  # Testing with Authentication
7
7
 
8
+ Real API references:
9
+
10
+ - `TestTokenFactory.createTestToken(opts)` — `libs/testing/src/auth/token-factory.ts:97` (plus `createAdminToken`, `createUserToken`, `createAnonymousToken`, `createExpiredToken`, `createTokenWithInvalidSignature`).
11
+ - `new MockOAuthServer(tokenFactory, options)` + `.start()` / `.stop()` — `libs/testing/src/auth/mock-oauth-server.ts:159`.
12
+ - `TestServer.start({ command, port })` — `libs/testing/src/server/test-server.ts:101`. Get a client with `McpTestClient.create({ baseUrl }).withToken(token).buildAndConnect()`.
13
+ - Roles, email, and other claims go inside `claims`, not as top-level fields. `CreateTokenOptions` only declares `sub`, `iss`, `aud`, `scopes`, `exp`, `claims`.
14
+
8
15
  ```typescript
9
- import { McpTestClient, TestServer, TestTokenFactory, MockOAuthServer } from '@frontmcp/testing';
10
- import Server from '../src/main';
16
+ // auth.e2e.spec.ts
17
+ import { McpTestClient, TestServer, TestTokenFactory } from '@frontmcp/testing';
11
18
 
12
19
  describe('Authenticated Server', () => {
13
20
  let server: TestServer;
14
21
  let tokenFactory: TestTokenFactory;
15
22
 
16
23
  beforeAll(async () => {
17
- server = await TestServer.create(Server);
24
+ server = await TestServer.start({
25
+ command: 'npx tsx src/main.ts',
26
+ port: 3010,
27
+ });
18
28
  tokenFactory = new TestTokenFactory({
19
29
  issuer: 'https://test-idp.example.com',
20
30
  audience: 'my-api',
@@ -22,82 +32,115 @@ describe('Authenticated Server', () => {
22
32
  });
23
33
 
24
34
  afterAll(async () => {
25
- await server.dispose();
35
+ await server.stop();
26
36
  });
27
37
 
28
- it('should reject unauthenticated requests', async () => {
29
- const client = await server.connect();
30
- const result = await client.callTool('protected_tool', {});
31
- expect(result.isError).toBe(true);
32
- await client.close();
38
+ it('rejects unauthenticated requests', async () => {
39
+ const client = await McpTestClient.create({ baseUrl: server.info.baseUrl })
40
+ .withTransport('streamable-http')
41
+ .withPublicMode() // do not request an anonymous token; send no Authorization header
42
+ .buildAndConnect();
43
+
44
+ const result = await client.tools.call('protected_tool', {});
45
+ expect(result).toBeError();
46
+
47
+ await client.disconnect();
33
48
  });
34
49
 
35
- it('should accept valid token', async () => {
36
- const token = await tokenFactory.createToken({
50
+ it('accepts a valid token', async () => {
51
+ const token = await tokenFactory.createTestToken({
37
52
  sub: 'user-123',
38
53
  scopes: ['read', 'write'],
39
54
  });
40
55
 
41
- const client = await server.connect({ authToken: token });
42
- const result = await client.callTool('protected_tool', { data: 'test' });
56
+ const client = await McpTestClient.create({ baseUrl: server.info.baseUrl })
57
+ .withTransport('streamable-http')
58
+ .withToken(token)
59
+ .buildAndConnect();
60
+
61
+ const result = await client.tools.call('protected_tool', { data: 'test' });
43
62
  expect(result).toBeSuccessful();
44
- await client.close();
63
+
64
+ await client.disconnect();
45
65
  });
46
66
 
47
- it('should enforce role-based access', async () => {
48
- const adminToken = await tokenFactory.createToken({
67
+ it('enforces role-based access', async () => {
68
+ const adminToken = await tokenFactory.createTestToken({
49
69
  sub: 'admin-1',
50
- roles: ['admin'],
70
+ claims: { roles: ['admin'] },
51
71
  });
52
- const userToken = await tokenFactory.createToken({
72
+ const userToken = await tokenFactory.createTestToken({
53
73
  sub: 'user-1',
54
- roles: ['user'],
74
+ claims: { roles: ['user'] },
55
75
  });
56
76
 
57
- const adminClient = await server.connect({ authToken: adminToken });
58
- const adminResult = await adminClient.callTool('admin_only_tool', {});
77
+ const adminClient = await McpTestClient.create({ baseUrl: server.info.baseUrl })
78
+ .withTransport('streamable-http')
79
+ .withToken(adminToken)
80
+ .buildAndConnect();
81
+ const adminResult = await adminClient.tools.call('admin_only_tool', {});
59
82
  expect(adminResult).toBeSuccessful();
60
83
 
61
- const userClient = await server.connect({ authToken: userToken });
62
- const userResult = await userClient.callTool('admin_only_tool', {});
63
- expect(userResult.isError).toBe(true);
84
+ const userClient = await McpTestClient.create({ baseUrl: server.info.baseUrl })
85
+ .withTransport('streamable-http')
86
+ .withToken(userToken)
87
+ .buildAndConnect();
88
+ const userResult = await userClient.tools.call('admin_only_tool', {});
89
+ expect(userResult).toBeError();
64
90
 
65
- await adminClient.close();
66
- await userClient.close();
91
+ await adminClient.disconnect();
92
+ await userClient.disconnect();
67
93
  });
68
94
  });
95
+ ```
96
+
97
+ ## Mock OAuth / OIDC server
98
+
99
+ `MockOAuthServer` serves JWKS, OAuth metadata, authorization, token, and userinfo endpoints. Construct it with a `TestTokenFactory`, call `.start()` to bind a port, and configure your MCP server to point at the returned `info.issuer` / `info.jwksUrl`.
69
100
 
70
- describe('OAuth Flow', () => {
101
+ ```typescript
102
+ // mock-oauth.e2e.spec.ts
103
+ import { MockOAuthServer, TestTokenFactory } from '@frontmcp/testing';
104
+
105
+ describe('Mock OAuth server', () => {
106
+ let tokenFactory: TestTokenFactory;
71
107
  let mockOAuth: MockOAuthServer;
72
108
 
73
109
  beforeAll(async () => {
74
- mockOAuth = await MockOAuthServer.create({
75
- issuer: 'https://test-idp.example.com',
76
- port: 9999,
110
+ tokenFactory = new TestTokenFactory();
111
+ mockOAuth = new MockOAuthServer(tokenFactory, {
112
+ autoApprove: true,
113
+ testUser: { sub: 'user-123', email: 'test@example.com' },
114
+ clientId: 'test-client',
115
+ validRedirectUris: ['http://localhost:3001/callback'],
77
116
  });
117
+ await mockOAuth.start();
78
118
  });
79
119
 
80
120
  afterAll(async () => {
81
- await mockOAuth.close();
121
+ await mockOAuth.stop();
82
122
  });
83
123
 
84
- it('should complete OAuth authorization code flow', async () => {
85
- const { authorizationUrl } = await mockOAuth.startFlow({
86
- clientId: 'test-client',
87
- redirectUri: 'http://localhost:3001/callback',
88
- scopes: ['openid', 'profile'],
89
- });
90
- expect(authorizationUrl).toContain('code=');
124
+ it('exposes JWKS that verifies factory-issued tokens', async () => {
125
+ const jwks = await fetch(mockOAuth.info.jwksUrl).then((r) => r.json());
126
+ expect(jwks.keys.length).toBeGreaterThan(0);
127
+ });
128
+
129
+ it('issues tokens via the same factory', async () => {
130
+ const token = await tokenFactory.createTestToken({ sub: 'user-123' });
131
+ expect(token.split('.')).toHaveLength(3);
91
132
  });
92
133
  });
93
134
  ```
94
135
 
136
+ To run the full authorization-code-with-PKCE flow against the mock server, drive the standard OAuth endpoints (`/oauth/authorize`, `/oauth/token`) directly with `fetch` — the mock server auto-approves when `autoApprove: true` and `testUser` are set.
137
+
95
138
  ## Examples
96
139
 
97
- | Example | Level | Description |
98
- | --------------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------- |
99
- | [`oauth-flow-test`](../examples/test-auth/oauth-flow-test.md) | Advanced | Use `MockOAuthServer` to simulate an OAuth identity provider and test the authorization code flow. |
100
- | [`role-based-access-test`](../examples/test-auth/role-based-access-test.md) | Intermediate | Verify that tools enforce role-based access by testing admin and user tokens against protected endpoints. |
101
- | [`token-factory-test`](../examples/test-auth/token-factory-test.md) | Basic | Use `TestTokenFactory` to create tokens and verify authenticated and unauthenticated requests. |
140
+ | Example | Level | Description |
141
+ | --------------------------------------------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
142
+ | [`oauth-flow-test`](../examples/test-auth/oauth-flow-test.md) | Advanced | Use `MockOAuthServer` to simulate an OAuth/OIDC identity provider. The server publishes a JWKS endpoint backed by your `TestTokenFactory`, so any token created by that factory is valid against the mock IDP. |
143
+ | [`role-based-access-test`](../examples/test-auth/role-based-access-test.md) | Intermediate | Verify that tools enforce role-based access by testing admin and user tokens against protected endpoints. |
144
+ | [`token-factory-test`](../examples/test-auth/token-factory-test.md) | Basic | Use `TestTokenFactory` to create tokens and verify authenticated and unauthenticated requests. |
102
145
 
103
146
  > See all examples in [`examples/test-auth/`](../examples/test-auth/)
@@ -37,7 +37,7 @@ describe('Browser Build', () => {
37
37
  ## Testing with Playwright (.pw.spec.ts)
38
38
 
39
39
  ```typescript
40
- import { test, expect } from '@playwright/test';
40
+ import { expect, test } from '@playwright/test';
41
41
 
42
42
  test('browser MCP client loads tools', async ({ page }) => {
43
43
  await page.goto('http://localhost:3000');
@@ -5,20 +5,38 @@ description: In-memory testing with create() and connectOpenAI/connectClaude wit
5
5
 
6
6
  # Testing with Direct Client (No HTTP)
7
7
 
8
- Uses `connect()` or `create()` for in-memory testing without HTTP overhead.
8
+ Use `create()` for an in-memory `DirectMcpServer` and `connectOpenAI()` / `connectClaude()` for an in-memory `DirectClient` with platform-specific tool formatting. None of these start an HTTP server — they wire client and server through an in-memory transport.
9
+
10
+ Real API references:
11
+
12
+ - `create(config)` — `libs/sdk/src/direct/create.ts`. Returns `DirectMcpServer` with `listTools`, `callTool`, `listResources`, `readResource`, `listPrompts`, `getPrompt`, `dispose`.
13
+ - `connectOpenAI(config, options?)` / `connectClaude(config, options?)` — `libs/sdk/src/direct/connect.ts:159` / `:200`. Both take a `FrontMcpConfigInput` (decorated `@FrontMcp` class or config object) and return a `DirectClient`. There is no `serve` field; the in-memory transport is always used.
14
+ - Tools are class-based using the `@Tool` decorator (`libs/sdk/src/index.ts` — there is no `tool()` factory function).
9
15
 
10
16
  ```typescript
11
- import { connectOpenAI, create, tool, z } from '@frontmcp/sdk';
17
+ // direct-client.spec.ts
18
+ import { App, connectOpenAI, create, FrontMcp, Tool, ToolContext, z } from '@frontmcp/sdk';
12
19
 
13
- const AddTool = tool({
20
+ @Tool({
14
21
  name: 'add',
15
22
  description: 'Add numbers',
16
23
  inputSchema: { a: z.number(), b: z.number() },
17
24
  outputSchema: { sum: z.number() },
18
- })((input) => ({ sum: input.a + input.b }));
25
+ })
26
+ class AddTool extends ToolContext {
27
+ async execute(input: { a: number; b: number }) {
28
+ return { sum: input.a + input.b };
29
+ }
30
+ }
31
+
32
+ @App({ name: 'test-app', tools: [AddTool] })
33
+ class TestApp {}
34
+
35
+ @FrontMcp({ info: { name: 'test', version: '1.0.0' }, apps: [TestApp] })
36
+ class TestServerConfig {}
19
37
 
20
38
  describe('Direct Client Testing', () => {
21
- it('should call tools via create()', async () => {
39
+ it('calls tools via create() with a flat config', async () => {
22
40
  const server = await create({
23
41
  info: { name: 'test', version: '1.0.0' },
24
42
  tools: [AddTool],
@@ -26,17 +44,14 @@ describe('Direct Client Testing', () => {
26
44
  });
27
45
 
28
46
  const result = await server.callTool('add', { a: 2, b: 3 });
29
- expect(result.content[0].text).toContain('5');
47
+ // execute() returns { sum: 5 }; the framework wraps it as a CallToolResult.
48
+ expect(result.structuredContent).toEqual({ sum: 5 });
30
49
 
31
50
  await server.dispose();
32
51
  });
33
52
 
34
- it('should return OpenAI-formatted tools', async () => {
35
- const client = await connectOpenAI({
36
- info: { name: 'test', version: '1.0.0' },
37
- tools: [AddTool],
38
- serve: false,
39
- });
53
+ it('returns OpenAI-formatted tools', async () => {
54
+ const client = await connectOpenAI(TestServerConfig);
40
55
 
41
56
  const tools = await client.listTools();
42
57
  // OpenAI format: [{ type: 'function', function: { name, parameters } }]
@@ -46,13 +61,8 @@ describe('Direct Client Testing', () => {
46
61
  await client.close();
47
62
  });
48
63
 
49
- it('should return Claude-formatted tools', async () => {
50
- const { connectClaude } = await import('@frontmcp/sdk');
51
- const client = await connectClaude({
52
- info: { name: 'test', version: '1.0.0' },
53
- tools: [AddTool],
54
- serve: false,
55
- });
64
+ it('returns Claude-formatted tools', async () => {
65
+ const client = await connectClaude(TestServerConfig);
56
66
 
57
67
  const tools = await client.listTools();
58
68
  // Claude format: [{ name, description, input_schema }]
@@ -5,50 +5,62 @@ description: Full MCP protocol E2E tests over HTTP with McpTestClient and TestSe
5
5
 
6
6
  # E2E Testing with McpTestClient (HTTP Handler)
7
7
 
8
- Tests the full MCP protocol over HTTP — validates tools, resources, prompts end-to-end.
8
+ Tests the full MCP protocol over HTTP — validates tools, resources, prompts end-to-end. This is the manual alternative to the fixture API in `setup-testing` and is useful when you need fine-grained control over server lifecycle, transport, or auth.
9
+
10
+ Real API references:
11
+
12
+ - `TestServer.start({ command, port })` returns a `TestServer` instance with `info.baseUrl` and `stop()` — `libs/testing/src/server/test-server.ts:101`. There is no `TestServer.create(ServerClass)`.
13
+ - Build a client with `await McpTestClient.create({ baseUrl }).withTransport('streamable-http').buildAndConnect()` — `libs/testing/src/client/mcp-test-client.builder.ts`.
14
+ - The public client API is namespaced: `client.tools.list()`, `client.tools.call(name, args)`, `client.resources.list()`, `client.resources.read(uri)`, `client.prompts.list()`, `client.prompts.get(name, args)`, `client.disconnect()` — `libs/testing/src/client/mcp-test-client.ts:306-402`.
9
15
 
10
16
  ```typescript
17
+ // server.e2e.spec.ts
11
18
  import { McpTestClient, TestServer } from '@frontmcp/testing';
12
- import Server from '../src/main';
13
19
 
14
20
  describe('Server E2E', () => {
15
21
  let client: McpTestClient;
16
22
  let server: TestServer;
17
23
 
18
24
  beforeAll(async () => {
19
- server = await TestServer.create(Server);
20
- client = await server.connect();
25
+ server = await TestServer.start({
26
+ command: 'npx tsx src/main.ts',
27
+ port: 3020,
28
+ });
29
+
30
+ client = await McpTestClient.create({ baseUrl: server.info.baseUrl })
31
+ .withTransport('streamable-http')
32
+ .buildAndConnect();
21
33
  });
22
34
 
23
35
  afterAll(async () => {
24
- await client.close();
25
- await server.dispose();
36
+ await client.disconnect();
37
+ await server.stop();
26
38
  });
27
39
 
28
- it('should list all tools', async () => {
29
- const { tools } = await client.listTools();
40
+ it('lists all tools', async () => {
41
+ const tools = await client.tools.list();
30
42
  expect(tools.length).toBeGreaterThan(0);
31
43
  expect(tools).toContainTool('add_numbers');
32
44
  });
33
45
 
34
- it('should call a tool and get result', async () => {
35
- const result = await client.callTool('add_numbers', { a: 5, b: 3 });
46
+ it('calls a tool and gets a successful result', async () => {
47
+ const result = await client.tools.call('add_numbers', { a: 5, b: 3 });
36
48
  expect(result).toBeSuccessful();
37
- expect(result.content[0].text).toContain('8');
49
+ expect(result).toHaveTextContent('8');
38
50
  });
39
51
 
40
- it('should return error for invalid input', async () => {
41
- const result = await client.callTool('add_numbers', { a: 'bad' });
42
- expect(result.isError).toBe(true);
52
+ it('returns an error for invalid input', async () => {
53
+ const result = await client.tools.call('add_numbers', { a: 'bad' });
54
+ expect(result).toBeError();
43
55
  });
44
56
 
45
- it('should list resources', async () => {
46
- const { resources } = await client.listResources();
47
- expect(resources.length).toBeGreaterThanOrEqual(0);
57
+ it('lists resources', async () => {
58
+ const resources = await client.resources.list();
59
+ expect(Array.isArray(resources)).toBe(true);
48
60
  });
49
61
 
50
- it('should get a prompt', async () => {
51
- const result = await client.getPrompt('summarize', { topic: 'testing' });
62
+ it('gets a prompt', async () => {
63
+ const result = await client.prompts.get('summarize', { topic: 'testing' });
52
64
  expect(result.messages).toBeDefined();
53
65
  expect(result.messages.length).toBeGreaterThan(0);
54
66
  });
@@ -12,16 +12,20 @@ import { AddTool } from '../tools/add.tool';
12
12
 
13
13
  describe('AddTool', () => {
14
14
  it('should add two numbers', async () => {
15
- // Create mock context
15
+ // Mock the ExecutionContextBase API surface (`get`, `tryGet`, `scope`, `fail`,
16
+ // `mark`, `fetch`) plus `notify` from ToolContext. Add `notify` only when the
17
+ // tool actually calls `this.notify(...)`.
18
+ // Real API: libs/sdk/src/common/interfaces/execution-context.interface.ts
16
19
  const ctx = {
17
20
  get: jest.fn(),
18
21
  tryGet: jest.fn(),
22
+ scope: { get: jest.fn(), tryGet: jest.fn() },
19
23
  fail: jest.fn((err) => {
20
24
  throw err;
21
25
  }),
22
26
  mark: jest.fn(),
27
+ fetch: jest.fn(),
23
28
  notify: jest.fn(),
24
- respondProgress: jest.fn(),
25
29
  } as unknown as ToolContext;
26
30
 
27
31
  const tool = new AddTool();