@cyanheads/mcp-ts-core 0.8.6 → 0.8.7
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.
- package/CLAUDE.md +1 -1
- package/README.md +1 -1
- package/changelog/0.8.x/0.8.7.md +16 -0
- package/dist/logs/combined.log +4 -4
- package/dist/logs/error.log +4 -4
- package/package.json +1 -2
- package/skills/field-test/SKILL.md +24 -17
package/CLAUDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent Protocol
|
|
2
2
|
|
|
3
|
-
**Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.8.
|
|
3
|
+
**Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.8.7
|
|
4
4
|
**npm:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) · **Docker:** [ghcr.io/cyanheads/mcp-ts-core](https://ghcr.io/cyanheads/mcp-ts-core)
|
|
5
5
|
|
|
6
6
|
> **Developer note:** Never assume. Read related files and docs before making changes. Read full file content for context. Never edit a file before reading it.
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
7
7
|
|
|
8
|
-
[](./CHANGELOG.md) [](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [](https://modelcontextprotocol.io/) [](./LICENSE)
|
|
9
9
|
|
|
10
10
|
[](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Remove `dev` watch script (finishes 0.8.6 dev-vs-prod cleanup); fix field-test helper state collision when concurrent sessions run from different project directories."
|
|
3
|
+
breaking: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 0.8.7 — 2026-04-29
|
|
7
|
+
|
|
8
|
+
Follow-up to 0.8.6 plus a field-test helper bug fix. The `dev` script was the last watch-mode entry point producing the same dev-vs-prod split 0.8.6 closed for `dev:stdio`/`dev:http`; removing it standardizes every developer and smoke-test path on `bun run rebuild && bun run start:stdio` (or `start:http`).
|
|
9
|
+
|
|
10
|
+
## Removed
|
|
11
|
+
|
|
12
|
+
- **`package.json`** — `dev` script (`bun --watch src/index.ts`). Use `bun run rebuild && bun run start:stdio` (or `start:http`) instead.
|
|
13
|
+
|
|
14
|
+
## Fixed
|
|
15
|
+
|
|
16
|
+
- **`skills/field-test/SKILL.md` v2.2 → v2.3** ([#90](https://github.com/cyanheads/mcp-ts-core/issues/90)) — Helper state and logs lived at fixed `/tmp/mcp-field-test.{env,build.log,server.log,init-*,call-body}` paths. Concurrent field-tests across different project trees silently overwrote each other's state, causing `mcp_call` to route JSON-RPC traffic to the wrong server and return another project's tool output. Helper now namespaces every per-session file under `/tmp/mcp-field-test-<8charPWDhash>` (state file, build log, server log, init/call scratch files), so parallel sessions in different directories no longer collide. Helper file path itself stays singleton (content is identical across projects).
|
package/dist/logs/combined.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{"level":50,"time":
|
|
2
|
-
{"level":50,"time":
|
|
3
|
-
{"level":50,"time":
|
|
4
|
-
{"level":50,"time":
|
|
1
|
+
{"level":50,"time":1777509241429,"env":"testing","version":"0.0.0-test","pid":42732,"requestId":"95RR8-CCDL5","timestamp":"2026-04-30T00:34:01.428Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"cf1e0b94b52d79d440a36946bd597ba0ff7fe2d3dfb4fdd949b5c82c5aad683d","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant"},"errorData":{"sessionId":"cf1e0b94b52d79d440a36946bd597ba0ff7fe2d3dfb4fdd949b5c82c5aad683d","toolName":"scoped_echo","requestId":"95RR8-CCDL5","timestamp":"2026-04-30T00:34:01.428Z","tenantId":"authz-tenant","operation":"HandleToolRequest","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant"},"originalErrorName":"McpError","originalMessage":"Insufficient permissions.","originalStack":"McpError: Insufficient permissions.\n at forbidden (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:58)\n at withRequiredScopes (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:61:15)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:133:17)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Insufficient permissions.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:169:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:168:26)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
2
|
+
{"level":50,"time":1777509242077,"env":"testing","version":"0.8.7","pid":42736,"requestId":"UMJV2-0KT5A","timestamp":"2026-04-30T00:34:02.077Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"UMJV2-0KT5A","timestamp":"2026-04-30T00:34:02.077Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Missing or invalid Authorization header. Bearer scheme required.","originalStack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at authMiddleware (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/authMiddleware.js:64:19)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpTransport.js:232:22)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at cors2 (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/middleware/cors/index.js:82:11)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:169:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Missing or invalid Authorization header. Bearer scheme required."}
|
|
3
|
+
{"level":50,"time":1777509242091,"env":"testing","version":"0.8.7","pid":42736,"requestId":"H705O-NGS51","timestamp":"2026-04-30T00:34:02.090Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"H705O-NGS51","timestamp":"2026-04-30T00:34:02.090Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Token has expired.","originalStack":"McpError: Token has expired.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at handleJoseVerifyError (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/claimParser.js:56:11)\n at verify (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/strategies/jwtStrategy.js:91:13)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Token has expired.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:169:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Token has expired."}
|
|
4
|
+
{"level":50,"time":1777509242094,"env":"testing","version":"0.8.7","pid":42736,"requestId":"C7EUG-OQZOM","timestamp":"2026-04-30T00:34:02.094Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"GET","errorData":{"path":"/mcp","method":"GET","requestId":"C7EUG-OQZOM","timestamp":"2026-04-30T00:34:02.094Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Missing or invalid Authorization header. Bearer scheme required.","originalStack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at authMiddleware (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/authMiddleware.js:64:19)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpTransport.js:232:22)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at cors2 (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/middleware/cors/index.js:82:11)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:169:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Missing or invalid Authorization header. Bearer scheme required."}
|
package/dist/logs/error.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{"level":50,"time":
|
|
2
|
-
{"level":50,"time":
|
|
3
|
-
{"level":50,"time":
|
|
4
|
-
{"level":50,"time":
|
|
1
|
+
{"level":50,"time":1777509241429,"env":"testing","version":"0.0.0-test","pid":42732,"requestId":"95RR8-CCDL5","timestamp":"2026-04-30T00:34:01.428Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"cf1e0b94b52d79d440a36946bd597ba0ff7fe2d3dfb4fdd949b5c82c5aad683d","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant"},"errorData":{"sessionId":"cf1e0b94b52d79d440a36946bd597ba0ff7fe2d3dfb4fdd949b5c82c5aad683d","toolName":"scoped_echo","requestId":"95RR8-CCDL5","timestamp":"2026-04-30T00:34:01.428Z","tenantId":"authz-tenant","operation":"HandleToolRequest","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant"},"originalErrorName":"McpError","originalMessage":"Insufficient permissions.","originalStack":"McpError: Insufficient permissions.\n at forbidden (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:58)\n at withRequiredScopes (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:61:15)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:133:17)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Insufficient permissions.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:169:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:168:26)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
2
|
+
{"level":50,"time":1777509242077,"env":"testing","version":"0.8.7","pid":42736,"requestId":"UMJV2-0KT5A","timestamp":"2026-04-30T00:34:02.077Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"UMJV2-0KT5A","timestamp":"2026-04-30T00:34:02.077Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Missing or invalid Authorization header. Bearer scheme required.","originalStack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at authMiddleware (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/authMiddleware.js:64:19)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpTransport.js:232:22)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at cors2 (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/middleware/cors/index.js:82:11)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:169:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Missing or invalid Authorization header. Bearer scheme required."}
|
|
3
|
+
{"level":50,"time":1777509242091,"env":"testing","version":"0.8.7","pid":42736,"requestId":"H705O-NGS51","timestamp":"2026-04-30T00:34:02.090Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"H705O-NGS51","timestamp":"2026-04-30T00:34:02.090Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Token has expired.","originalStack":"McpError: Token has expired.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at handleJoseVerifyError (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/claimParser.js:56:11)\n at verify (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/strategies/jwtStrategy.js:91:13)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Token has expired.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:169:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Token has expired."}
|
|
4
|
+
{"level":50,"time":1777509242094,"env":"testing","version":"0.8.7","pid":42736,"requestId":"C7EUG-OQZOM","timestamp":"2026-04-30T00:34:02.094Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"GET","errorData":{"path":"/mcp","method":"GET","requestId":"C7EUG-OQZOM","timestamp":"2026-04-30T00:34:02.094Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Missing or invalid Authorization header. Bearer scheme required.","originalStack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at authMiddleware (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/authMiddleware.js:64:19)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpTransport.js:232:22)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at cors2 (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/middleware/cors/index.js:82:11)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:169:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Missing or invalid Authorization header. Bearer scheme required."}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/mcp-ts-core",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7",
|
|
4
4
|
"mcpName": "io.github.cyanheads/mcp-ts-core",
|
|
5
5
|
"description": "Agent-native TypeScript framework for building MCP servers. Declarative definitions with auth, multi-backend storage, OpenTelemetry, and first-class support for Bun/Node/Cloudflare Workers.",
|
|
6
6
|
"main": "dist/core/index.js",
|
|
@@ -121,7 +121,6 @@
|
|
|
121
121
|
"start": "bun ./dist/index.js",
|
|
122
122
|
"start:stdio": "MCP_TRANSPORT_TYPE=stdio bun ./dist/index.js",
|
|
123
123
|
"start:http": "MCP_TRANSPORT_TYPE=http bun ./dist/index.js",
|
|
124
|
-
"dev": "bun --watch src/index.ts",
|
|
125
124
|
"devdocs": "bun run scripts/devdocs.ts",
|
|
126
125
|
"devcheck": "bun run scripts/devcheck.ts",
|
|
127
126
|
"rebuild": "bun run scripts/clean.ts && bun run build",
|
|
@@ -4,7 +4,7 @@ description: >
|
|
|
4
4
|
Exercise tools, resources, and prompts against a live HTTP server via MCP JSON-RPC over curl. Starts the server, surfaces the catalog, runs real and adversarial inputs, and produces a tight report with concrete findings and numbered follow-up options. Use after adding or modifying definitions, or when the user asks to test, try out, or verify their MCP surface.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "2.
|
|
7
|
+
version: "2.3"
|
|
8
8
|
audience: external
|
|
9
9
|
type: debug
|
|
10
10
|
---
|
|
@@ -27,7 +27,7 @@ This skill drives an HTTP server because curl + JSON-RPC is the most reliable ha
|
|
|
27
27
|
|
|
28
28
|
### 1. Start the server
|
|
29
29
|
|
|
30
|
-
Write the helper to `/tmp/mcp-field-test.sh` once, then source it in every subsequent Bash call. Helper keeps PID / URL / session id in `/tmp/mcp-field-test
|
|
30
|
+
Write the helper to `/tmp/mcp-field-test.sh` once, then source it in every subsequent Bash call. Helper keeps PID / URL / session id in a per-`$PWD` state file (`/tmp/mcp-field-test-<hash>.env`) so state survives across tool invocations and concurrent field-tests in different project trees don't clobber each other.
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
33
|
cat > /tmp/mcp-field-test.sh <<'HELPER_EOF'
|
|
@@ -36,29 +36,36 @@ cat > /tmp/mcp-field-test.sh <<'HELPER_EOF'
|
|
|
36
36
|
# Surfaces failures aggressively — field test is for finding things that fail,
|
|
37
37
|
# so the helper auto-tails logs and prints HTTP status/body on errors instead
|
|
38
38
|
# of swallowing them.
|
|
39
|
-
|
|
39
|
+
#
|
|
40
|
+
# State and log paths are namespaced by an 8-char hash of $PWD so concurrent
|
|
41
|
+
# field-tests across different project trees don't clobber each other (see
|
|
42
|
+
# https://github.com/cyanheads/mcp-ts-core/issues/90).
|
|
43
|
+
PREFIX="/tmp/mcp-field-test-$(printf '%s' "$PWD" | shasum | cut -c1-8)"
|
|
44
|
+
STATE_FILE="${PREFIX}.env"
|
|
45
|
+
BUILD_LOG="${PREFIX}-build.log"
|
|
46
|
+
SERVER_LOG="${PREFIX}-server.log"
|
|
40
47
|
[ -f "$STATE_FILE" ] && . "$STATE_FILE"
|
|
41
48
|
|
|
42
49
|
mcp_start() {
|
|
43
50
|
local dir="${1:-$PWD}"
|
|
44
51
|
echo "building $dir ..."
|
|
45
|
-
if ! (cd "$dir" && bun run rebuild)
|
|
46
|
-
echo "BUILD FAILED — last 30 lines of
|
|
47
|
-
tail -30
|
|
52
|
+
if ! (cd "$dir" && bun run rebuild) >"$BUILD_LOG" 2>&1; then
|
|
53
|
+
echo "BUILD FAILED — last 30 lines of $BUILD_LOG:"
|
|
54
|
+
tail -30 "$BUILD_LOG"
|
|
48
55
|
return 1
|
|
49
56
|
fi
|
|
50
57
|
echo "starting server ..."
|
|
51
|
-
(cd "$dir" && bun run start:http)
|
|
58
|
+
(cd "$dir" && bun run start:http) >"$SERVER_LOG" 2>&1 &
|
|
52
59
|
local pid=$!
|
|
53
60
|
local line=""
|
|
54
61
|
for _ in $(seq 1 40); do
|
|
55
|
-
line=$(grep -Eo 'listening at http://[^" ]+/mcp'
|
|
62
|
+
line=$(grep -Eo 'listening at http://[^" ]+/mcp' "$SERVER_LOG" | head -1)
|
|
56
63
|
[ -n "$line" ] && break
|
|
57
64
|
sleep 0.25
|
|
58
65
|
done
|
|
59
66
|
if [ -z "$line" ]; then
|
|
60
|
-
echo "server failed to start within 10s — last 30 lines of
|
|
61
|
-
tail -30
|
|
67
|
+
echo "server failed to start within 10s — last 30 lines of $SERVER_LOG:"
|
|
68
|
+
tail -30 "$SERVER_LOG"
|
|
62
69
|
kill "$pid" 2>/dev/null
|
|
63
70
|
return 1
|
|
64
71
|
fi
|
|
@@ -75,13 +82,13 @@ EOF
|
|
|
75
82
|
|
|
76
83
|
mcp_init() {
|
|
77
84
|
[ -z "$MCP_URL" ] && { echo "run mcp_start first"; return 1; }
|
|
78
|
-
local hdr="
|
|
79
|
-
local body_file="
|
|
85
|
+
local hdr="${PREFIX}-init-headers.txt"
|
|
86
|
+
local body_file="${PREFIX}-init-body.txt"
|
|
80
87
|
local status
|
|
81
88
|
status=$(curl -sS -D "$hdr" -o "$body_file" -w '%{http_code}' -X POST "$MCP_URL" \
|
|
82
89
|
-H "Content-Type: application/json" \
|
|
83
90
|
-H "Accept: application/json, text/event-stream" \
|
|
84
|
-
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"field-test","version":"2.
|
|
91
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"field-test","version":"2.3"}}}')
|
|
85
92
|
local sid; sid=$(grep -i '^mcp-session-id:' "$hdr" | awk '{print $2}' | tr -d '\r\n')
|
|
86
93
|
if [ -z "$sid" ]; then
|
|
87
94
|
echo "init failed — HTTP $status, no Mcp-Session-Id header returned"
|
|
@@ -119,7 +126,7 @@ mcp_call() {
|
|
|
119
126
|
else
|
|
120
127
|
body=$(printf '{"jsonrpc":"2.0","id":%d,"method":"%s","params":%s}' "$RANDOM" "$method" "$params")
|
|
121
128
|
fi
|
|
122
|
-
local resp_file="
|
|
129
|
+
local resp_file="${PREFIX}-call-body.txt"
|
|
123
130
|
local status
|
|
124
131
|
status=$(curl -sS -o "$resp_file" -w '%{http_code}' -X POST "$MCP_URL" \
|
|
125
132
|
-H "Content-Type: application/json" \
|
|
@@ -141,11 +148,11 @@ mcp_call() {
|
|
|
141
148
|
|
|
142
149
|
# Tail the server log. Useful when a call surprises you — pino startup banner,
|
|
143
150
|
# definition lint diagnostics, request handler errors, upstream calls, and
|
|
144
|
-
# rate-limit warnings live in
|
|
151
|
+
# rate-limit warnings live in the per-session server log.
|
|
145
152
|
# Usage: mcp_log [N] (default: 50 lines)
|
|
146
153
|
mcp_log() {
|
|
147
154
|
local n="${1:-50}"
|
|
148
|
-
tail -n "$n"
|
|
155
|
+
tail -n "$n" "$SERVER_LOG"
|
|
149
156
|
}
|
|
150
157
|
|
|
151
158
|
mcp_stop() {
|
|
@@ -254,7 +261,7 @@ Use `TaskCreate` — one task per definition. Mark complete as you go. Don't bat
|
|
|
254
261
|
|
|
255
262
|
For each call, capture: input sent, response (trim huge payloads to files), whether `isError: true` appeared, anything surprising (slow response, parity drift, unhelpful text, crash).
|
|
256
263
|
|
|
257
|
-
When a call surprises you — slow, hangs, returns terse output, surfaces an unhelpful error — run `. /tmp/mcp-field-test.sh && mcp_log` to tail the server log. The pino startup banner, request handler errors, upstream API call traces, and rate-limit warnings all land in
|
|
264
|
+
When a call surprises you — slow, hangs, returns terse output, surfaces an unhelpful error — run `. /tmp/mcp-field-test.sh && mcp_log` to tail the server log. The pino startup banner, request handler errors, upstream API call traces, and rate-limit warnings all land in the per-session server log (read via `mcp_log`) rather than coming back through `mcp_call`. Don't guess at runtime behavior from response text alone.
|
|
258
265
|
|
|
259
266
|
**Interpreting responses**
|
|
260
267
|
|