@quidli/connect-mcp 0.6.4 → 0.6.5

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/dist/mount.d.ts CHANGED
@@ -8,5 +8,8 @@ export interface ConnectMcpMountOptions {
8
8
  }
9
9
  export declare function resolveEmbeddedApiBaseUrl(port: number, env?: NodeJS.ProcessEnv): string;
10
10
  export declare function isConnectMcpHost(hostname: string, env?: NodeJS.ProcessEnv): boolean;
11
- export declare function normalizeAcceptHeader(req: Pick<Request, 'headers'>): void;
11
+ type NormalizableRequest = Pick<Request, 'headers'> & {
12
+ rawHeaders?: string[];
13
+ };
14
+ export declare function normalizeAcceptHeader(req: NormalizableRequest): void;
12
15
  export declare function mountConnectMcpHttp(router: IRouter, options: ConnectMcpMountOptions): void;
package/dist/mount.js CHANGED
@@ -51,12 +51,44 @@ export function isConnectMcpHost(hostname, env = process.env) {
51
51
  // wildcards). A client that genuinely accepts neither is left alone and still
52
52
  // gets its 406.
53
53
  const CANONICAL_ACCEPT = 'application/json, text/event-stream';
54
+ // The SDK's StreamableHTTPServerTransport (>= 1.26) is a wrapper that converts the
55
+ // Node request into a web-standard Request using @hono/node-server. That converter
56
+ // rebuilds the header set from `req.rawHeaders` and never reads `req.headers`, so
57
+ // writing only `req.headers.accept` is invisible to the transport and the 406 still
58
+ // fires. Write both: `headers` for anything else in the stack, `rawHeaders` for the
59
+ // SDK. Duplicate Accept entries are collapsed, because `new Headers()` would comma
60
+ // join them back into a value we did not intend.
61
+ function setAcceptHeader(req, value) {
62
+ req.headers.accept = value;
63
+ const raw = req.rawHeaders;
64
+ if (!Array.isArray(raw)) {
65
+ return;
66
+ }
67
+ const rebuilt = [];
68
+ let written = false;
69
+ for (let i = 0; i + 1 < raw.length; i += 2) {
70
+ const key = raw[i];
71
+ if (key.toLowerCase() === 'accept') {
72
+ if (!written) {
73
+ rebuilt.push(key, value);
74
+ written = true;
75
+ }
76
+ continue;
77
+ }
78
+ rebuilt.push(key, raw[i + 1]);
79
+ }
80
+ if (!written) {
81
+ rebuilt.push('Accept', value);
82
+ }
83
+ raw.length = 0;
84
+ raw.push(...rebuilt);
85
+ }
54
86
  export function normalizeAcceptHeader(req) {
55
87
  const raw = req.headers.accept;
56
88
  const value = Array.isArray(raw) ? raw.join(',') : (raw ?? '');
57
89
  // No Accept header means "anything" per RFC 9110.
58
90
  if (!value.trim()) {
59
- req.headers.accept = CANONICAL_ACCEPT;
91
+ setAcceptHeader(req, CANONICAL_ACCEPT);
60
92
  return;
61
93
  }
62
94
  const types = value
@@ -65,7 +97,7 @@ export function normalizeAcceptHeader(req) {
65
97
  .filter(Boolean);
66
98
  const permits = (type) => types.includes(type) || types.includes('*/*') || types.includes(`${type.split('/')[0]}/*`);
67
99
  if (permits('application/json') && permits('text/event-stream')) {
68
- req.headers.accept = CANONICAL_ACCEPT;
100
+ setAcceptHeader(req, CANONICAL_ACCEPT);
69
101
  }
70
102
  }
71
103
  export function mountConnectMcpHttp(router, options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quidli/connect-mcp",
3
- "version": "0.6.4",
3
+ "version": "0.6.5",
4
4
  "description": "Onchain reputation and identity for AI agents: score onchain reputation across social accounts, resolve handles to EVM and Solana wallet addresses, and send USDC from any MCP client.",
5
5
  "keywords": [
6
6
  "mcp",