@meertrack/mcp 1.0.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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +313 -0
  3. package/dist/auth.d.ts +75 -0
  4. package/dist/auth.d.ts.map +1 -0
  5. package/dist/auth.js +109 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/client.d.ts +84 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +178 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/errors.d.ts +27 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +68 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/index.d.ts +13 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +77 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/logger.d.ts +48 -0
  20. package/dist/logger.d.ts.map +1 -0
  21. package/dist/logger.js +46 -0
  22. package/dist/logger.js.map +1 -0
  23. package/dist/prompts/competitor_deep_dive.d.ts +5 -0
  24. package/dist/prompts/competitor_deep_dive.d.ts.map +1 -0
  25. package/dist/prompts/competitor_deep_dive.js +48 -0
  26. package/dist/prompts/competitor_deep_dive.js.map +1 -0
  27. package/dist/prompts/index.d.ts +13 -0
  28. package/dist/prompts/index.d.ts.map +1 -0
  29. package/dist/prompts/index.js +20 -0
  30. package/dist/prompts/index.js.map +1 -0
  31. package/dist/prompts/weekly_recap.d.ts +5 -0
  32. package/dist/prompts/weekly_recap.d.ts.map +1 -0
  33. package/dist/prompts/weekly_recap.js +28 -0
  34. package/dist/prompts/weekly_recap.js.map +1 -0
  35. package/dist/prompts/whats_new.d.ts +5 -0
  36. package/dist/prompts/whats_new.d.ts.map +1 -0
  37. package/dist/prompts/whats_new.js +46 -0
  38. package/dist/prompts/whats_new.js.map +1 -0
  39. package/dist/server.d.ts +34 -0
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +43 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/tools/get_activity_item.d.ts +6 -0
  44. package/dist/tools/get_activity_item.d.ts.map +1 -0
  45. package/dist/tools/get_activity_item.js +33 -0
  46. package/dist/tools/get_activity_item.js.map +1 -0
  47. package/dist/tools/get_competitor.d.ts +6 -0
  48. package/dist/tools/get_competitor.d.ts.map +1 -0
  49. package/dist/tools/get_competitor.js +37 -0
  50. package/dist/tools/get_competitor.js.map +1 -0
  51. package/dist/tools/get_digest.d.ts +6 -0
  52. package/dist/tools/get_digest.d.ts.map +1 -0
  53. package/dist/tools/get_digest.js +33 -0
  54. package/dist/tools/get_digest.js.map +1 -0
  55. package/dist/tools/index.d.ts +20 -0
  56. package/dist/tools/index.d.ts.map +1 -0
  57. package/dist/tools/index.js +36 -0
  58. package/dist/tools/index.js.map +1 -0
  59. package/dist/tools/list_activities.d.ts +6 -0
  60. package/dist/tools/list_activities.d.ts.map +1 -0
  61. package/dist/tools/list_activities.js +87 -0
  62. package/dist/tools/list_activities.js.map +1 -0
  63. package/dist/tools/list_competitors.d.ts +6 -0
  64. package/dist/tools/list_competitors.d.ts.map +1 -0
  65. package/dist/tools/list_competitors.js +58 -0
  66. package/dist/tools/list_competitors.js.map +1 -0
  67. package/dist/tools/list_digests.d.ts +6 -0
  68. package/dist/tools/list_digests.d.ts.map +1 -0
  69. package/dist/tools/list_digests.js +63 -0
  70. package/dist/tools/list_digests.js.map +1 -0
  71. package/dist/tools/list_latest_digests.d.ts +6 -0
  72. package/dist/tools/list_latest_digests.d.ts.map +1 -0
  73. package/dist/tools/list_latest_digests.js +30 -0
  74. package/dist/tools/list_latest_digests.js.map +1 -0
  75. package/dist/tools/whoami.d.ts +6 -0
  76. package/dist/tools/whoami.d.ts.map +1 -0
  77. package/dist/tools/whoami.js +30 -0
  78. package/dist/tools/whoami.js.map +1 -0
  79. package/dist/transports/http.d.ts +58 -0
  80. package/dist/transports/http.d.ts.map +1 -0
  81. package/dist/transports/http.js +179 -0
  82. package/dist/transports/http.js.map +1 -0
  83. package/dist/transports/stdio.d.ts +12 -0
  84. package/dist/transports/stdio.d.ts.map +1 -0
  85. package/dist/transports/stdio.js +35 -0
  86. package/dist/transports/stdio.js.map +1 -0
  87. package/dist/types.d.ts +6204 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +359 -0
  90. package/dist/types.js.map +1 -0
  91. package/dist/version.d.ts +2 -0
  92. package/dist/version.d.ts.map +1 -0
  93. package/dist/version.js +5 -0
  94. package/dist/version.js.map +1 -0
  95. package/package.json +68 -0
@@ -0,0 +1,63 @@
1
+ import { z } from "zod";
2
+ import { DigestListResponse, paginationInput } from "../types.js";
3
+ import { toToolError } from "../errors.js";
4
+ export const LIST_DIGESTS_NAME = "list_digests";
5
+ export const LIST_DIGESTS_DESCRIPTION = [
6
+ "Wraps `GET /digests`. Returns cursor-paginated weekly digests (one per competitor per batch day) — the LLM-synthesized summaries. Unlike `list_activities`, pagination here has **no `total`**; use `has_more` / `next_cursor` only.",
7
+ "",
8
+ "Filters: `competitor_id` (narrow to one competitor), `from` / `to` (ISO 8601 date-time window on `period_start`).",
9
+ "",
10
+ "Chaining: For 'what happened last week across all competitors', prefer `list_latest_digests` — it's a one-shot. Use this when paging backward through history, or filtering to one competitor.",
11
+ "Errors: `invalid_parameter`, `invalid_cursor`, `unauthorized`, `rate_limited`.",
12
+ ].join("\n");
13
+ const inputSchema = {
14
+ competitor_id: z
15
+ .string()
16
+ .uuid()
17
+ .optional()
18
+ .describe("Narrow to one competitor's digests. Omit for all tracked competitors."),
19
+ from: z
20
+ .string()
21
+ .datetime({ offset: true })
22
+ .optional()
23
+ .describe("Inclusive lower bound on `period_start`, ISO 8601 with offset."),
24
+ to: z
25
+ .string()
26
+ .datetime({ offset: true })
27
+ .optional()
28
+ .describe("Inclusive upper bound on `period_start`, ISO 8601 with offset."),
29
+ limit: paginationInput.limit,
30
+ cursor: paginationInput.cursor,
31
+ };
32
+ export function registerListDigests(server, client) {
33
+ server.registerTool(LIST_DIGESTS_NAME, {
34
+ title: "List digests",
35
+ description: LIST_DIGESTS_DESCRIPTION,
36
+ inputSchema,
37
+ outputSchema: DigestListResponse.shape,
38
+ annotations: { readOnlyHint: true },
39
+ }, async (args) => {
40
+ try {
41
+ const params = {};
42
+ if (args.competitor_id)
43
+ params.competitor_id = [args.competitor_id];
44
+ if (args.from)
45
+ params.from = args.from;
46
+ if (args.to)
47
+ params.to = args.to;
48
+ if (args.limit !== undefined)
49
+ params.limit = args.limit;
50
+ if (args.cursor)
51
+ params.cursor = args.cursor;
52
+ const data = await client.listDigests(params);
53
+ return {
54
+ structuredContent: data,
55
+ content: [{ type: "text", text: JSON.stringify(data) }],
56
+ };
57
+ }
58
+ catch (err) {
59
+ return toToolError(err);
60
+ }
61
+ });
62
+ }
63
+ //# sourceMappingURL=list_digests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_digests.js","sourceRoot":"","sources":["../../src/tools/list_digests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEhD,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,sOAAsO;IACtO,EAAE;IACF,mHAAmH;IACnH,EAAE;IACF,gMAAgM;IAChM,gFAAgF;CACjF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,WAAW,GAAG;IAClB,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,IAAI,EAAE;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,uEAAuE,CAAC;IACpF,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SAC1B,QAAQ,EAAE;SACV,QAAQ,CAAC,gEAAgE,CAAC;IAC7E,EAAE,EAAE,CAAC;SACF,MAAM,EAAE;SACR,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SAC1B,QAAQ,EAAE;SACV,QAAQ,CAAC,gEAAgE,CAAC;IAC7E,KAAK,EAAE,eAAe,CAAC,KAAK;IAC5B,MAAM,EAAE,eAAe,CAAC,MAAM;CACtB,CAAC;AAEX,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,MAAuB;IAC5E,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,wBAAwB;QACrC,WAAW;QACX,YAAY,EAAE,kBAAkB,CAAC,KAAK;QACtC,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;KACpC,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAA6C,EAAE,CAAC;YAC5D,IAAI,IAAI,CAAC,aAAa;gBAAE,MAAM,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACpE,IAAI,IAAI,CAAC,IAAI;gBAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;YACvC,IAAI,IAAI,CAAC,EAAE;gBAAE,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACxD,IAAI,IAAI,CAAC,MAAM;gBAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC7C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAC9C,OAAO;gBACL,iBAAiB,EAAE,IAAI;gBACvB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;aACxD,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { MeertrackClient } from "../client.js";
3
+ export declare const LIST_LATEST_DIGESTS_NAME = "list_latest_digests";
4
+ export declare const LIST_LATEST_DIGESTS_DESCRIPTION: string;
5
+ export declare function registerListLatestDigests(server: McpServer, client: MeertrackClient): void;
6
+ //# sourceMappingURL=list_latest_digests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_latest_digests.d.ts","sourceRoot":"","sources":["../../src/tools/list_latest_digests.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAIpD,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAE9D,eAAO,MAAM,+BAA+B,QAKhC,CAAC;AAEb,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAsB1F"}
@@ -0,0 +1,30 @@
1
+ import { DigestLatestResponse } from "../types.js";
2
+ import { toToolError } from "../errors.js";
3
+ export const LIST_LATEST_DIGESTS_NAME = "list_latest_digests";
4
+ export const LIST_LATEST_DIGESTS_DESCRIPTION = [
5
+ "Wraps `GET /digests/latest`. No parameters. Returns the most recent digest per active competitor from the same batch day — a one-shot 'what happened this week across my tracked competitors'.",
6
+ "",
7
+ "Chaining: One-shot entry point — no prior call needed. If the user wants older weeks or a specific competitor's history, use `list_digests` instead.",
8
+ "Errors: `unauthorized`, `rate_limited`.",
9
+ ].join("\n");
10
+ export function registerListLatestDigests(server, client) {
11
+ server.registerTool(LIST_LATEST_DIGESTS_NAME, {
12
+ title: "List latest digests",
13
+ description: LIST_LATEST_DIGESTS_DESCRIPTION,
14
+ inputSchema: {},
15
+ outputSchema: DigestLatestResponse.shape,
16
+ annotations: { readOnlyHint: true },
17
+ }, async () => {
18
+ try {
19
+ const data = await client.listLatestDigests();
20
+ return {
21
+ structuredContent: data,
22
+ content: [{ type: "text", text: JSON.stringify(data) }],
23
+ };
24
+ }
25
+ catch (err) {
26
+ return toToolError(err);
27
+ }
28
+ });
29
+ }
30
+ //# sourceMappingURL=list_latest_digests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_latest_digests.js","sourceRoot":"","sources":["../../src/tools/list_latest_digests.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,CAAC,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AAE9D,MAAM,CAAC,MAAM,+BAA+B,GAAG;IAC7C,gMAAgM;IAChM,EAAE;IACF,sJAAsJ;IACtJ,yCAAyC;CAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,UAAU,yBAAyB,CAAC,MAAiB,EAAE,MAAuB;IAClF,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,+BAA+B;QAC5C,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,oBAAoB,CAAC,KAAK;QACxC,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;KACpC,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAC9C,OAAO;gBACL,iBAAiB,EAAE,IAAI;gBACvB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;aACxD,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { MeertrackClient } from "../client.js";
3
+ export declare const WHOAMI_NAME = "whoami";
4
+ export declare const WHOAMI_DESCRIPTION: string;
5
+ export declare function registerWhoami(server: McpServer, client: MeertrackClient): void;
6
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/tools/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAIpD,eAAO,MAAM,WAAW,WAAW,CAAC;AAEpC,eAAO,MAAM,kBAAkB,QAKnB,CAAC;AAEb,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAsB/E"}
@@ -0,0 +1,30 @@
1
+ import { MeResponse } from "../types.js";
2
+ import { toToolError } from "../errors.js";
3
+ export const WHOAMI_NAME = "whoami";
4
+ export const WHOAMI_DESCRIPTION = [
5
+ "Wraps `GET /me`. Confirms which workspace and API key the agent is authenticated as and returns the current subscription, competitor budget, and rate-limit snapshot.",
6
+ "",
7
+ "Chaining: Call first in a session to verify auth and workspace identity before any other tool.",
8
+ "Errors: `unauthorized` (key is invalid or revoked — mint a new one), `rate_limited` (retry after `X-RateLimit-Reset`).",
9
+ ].join("\n");
10
+ export function registerWhoami(server, client) {
11
+ server.registerTool(WHOAMI_NAME, {
12
+ title: "Who am I?",
13
+ description: WHOAMI_DESCRIPTION,
14
+ inputSchema: {},
15
+ outputSchema: MeResponse.shape,
16
+ annotations: { readOnlyHint: true },
17
+ }, async () => {
18
+ try {
19
+ const data = await client.me();
20
+ return {
21
+ structuredContent: data,
22
+ content: [{ type: "text", text: JSON.stringify(data) }],
23
+ };
24
+ }
25
+ catch (err) {
26
+ return toToolError(err);
27
+ }
28
+ });
29
+ }
30
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/tools/whoami.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEpC,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,uKAAuK;IACvK,EAAE;IACF,gGAAgG;IAChG,wHAAwH;CACzH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,UAAU,cAAc,CAAC,MAAiB,EAAE,MAAuB;IACvE,MAAM,CAAC,YAAY,CACjB,WAAW,EACX;QACE,KAAK,EAAE,WAAW;QAClB,WAAW,EAAE,kBAAkB;QAC/B,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,UAAU,CAAC,KAAK;QAC9B,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;KACpC,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,EAAE,EAAE,CAAC;YAC/B,OAAO;gBACL,iBAAiB,EAAE,IAAI;gBACvB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;aACxD,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { Hono } from "hono";
2
+ import { buildWwwAuthenticateHeader } from "../auth.js";
3
+ import { type Logger } from "../logger.js";
4
+ /**
5
+ * Streamable HTTP transport (MCP spec 2025-11-25 §transports).
6
+ *
7
+ * Shape:
8
+ * POST /mcp — JSON-RPC request/response, delegated to the SDK transport
9
+ * which enforces the dual-Accept header, Content-Type, and
10
+ * `MCP-Protocol-Version`.
11
+ * GET /mcp — 405 (V1 is stateless with no server-initiated notifications).
12
+ * DELETE /mcp — 405 (V1 is stateless; `Mcp-Session-Id` is never issued).
13
+ * GET /health — Fly.io health probe.
14
+ * GET /.well-known/oauth-protected-resource — RFC 9728 PRM stub (required
15
+ * by spec §Authorization for spec-conformant clients to discover how
16
+ * to authenticate).
17
+ *
18
+ * Per-request server: every POST builds a fresh `McpServer` bound to that
19
+ * request's bearer. This is the standard stateless pattern — it isolates
20
+ * per-key auth state and avoids cross-bearer leakage. It is NOT a performance
21
+ * mistake. If profiling ever shows `McpServer` construction is a hot spot, the
22
+ * fix is to hoist tool registration to module scope (tool definitions are
23
+ * static) and only rebuild the per-request auth/client binding — **do not**
24
+ * share a mutable server across requests with different bearers. Not a v1
25
+ * optimization.
26
+ */
27
+ export interface CreateHttpAppOptions {
28
+ /** Optional upstream override (otherwise resolved from env). */
29
+ baseUrl?: string;
30
+ /**
31
+ * Allowlist for the `Origin` header (DNS rebinding protection, spec
32
+ * §transports line 104). Requests without an `Origin` header pass (non-
33
+ * browser clients like `curl` / `npx` don't set it).
34
+ */
35
+ allowedOrigins: string[];
36
+ /**
37
+ * Public URL of the PRM document, embedded in `WWW-Authenticate` on 401s.
38
+ * Used verbatim — include scheme + host + path.
39
+ */
40
+ protectedResourceMetadataUrl: string;
41
+ /** Optional fetch override for tests. Threaded into `buildServer`. */
42
+ fetchImpl?: typeof fetch;
43
+ /** Optional logger override (tests use a sink that captures lines). */
44
+ logger?: Logger;
45
+ }
46
+ export declare const HEALTH_PATH = "/health";
47
+ export declare const MCP_PATH = "/mcp";
48
+ export declare const PRM_PATH = "/.well-known/oauth-protected-resource";
49
+ export declare function createHttpApp(options: CreateHttpAppOptions): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
50
+ /**
51
+ * Resolve the PRM URL from config + the incoming request. Used by the
52
+ * entrypoint when users don't override the metadata URL explicitly: derive it
53
+ * from the first request's `Host`. For the production Fly deploy, this config
54
+ * is set at startup via `MEERTRACK_MCP_PRM_URL` to the public HTTPS URL.
55
+ */
56
+ export declare function defaultProtectedResourceMetadataUrl(host: string, protocol?: "http" | "https"): string;
57
+ export { buildWwwAuthenticateHeader };
58
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EACL,0BAA0B,EAG3B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAA2B,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,4BAA4B,EAAE,MAAM,CAAC;IACrC,sEAAsE;IACtE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,QAAQ,SAAS,CAAC;AAC/B,eAAO,MAAM,QAAQ,0CAA0C,CAAC;AAEhE,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,8EAqC1D;AAgKD;;;;;GAKG;AACH,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,GAAG,OAAiB,GAAG,MAAM,CAE9G;AAED,OAAO,EAAE,0BAA0B,EAAE,CAAC"}
@@ -0,0 +1,179 @@
1
+ import { Hono } from "hono";
2
+ import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
3
+ import { buildWwwAuthenticateHeader, extractHttpBearer, } from "../auth.js";
4
+ import { buildServer } from "../server.js";
5
+ import { logger as defaultLogger } from "../logger.js";
6
+ export const HEALTH_PATH = "/health";
7
+ export const MCP_PATH = "/mcp";
8
+ export const PRM_PATH = "/.well-known/oauth-protected-resource";
9
+ export function createHttpApp(options) {
10
+ const app = new Hono();
11
+ // Origin allowlist — runs before routing so it protects every path. The SDK
12
+ // also has deprecated built-in origin validation; we enforce it at the
13
+ // transport edge per the spec's current guidance.
14
+ app.use("*", async (c, next) => {
15
+ const origin = c.req.header("origin");
16
+ if (origin && !options.allowedOrigins.includes(origin)) {
17
+ return c.json({ error: { code: "forbidden_origin", message: `Origin not allowed: ${origin}` } }, 403);
18
+ }
19
+ await next();
20
+ });
21
+ app.get(HEALTH_PATH, (c) => c.json({ ok: true }));
22
+ app.get(PRM_PATH, (c) => c.json({
23
+ resource: prmResourceFor(options.protectedResourceMetadataUrl),
24
+ authorization_servers: [],
25
+ bearer_methods_supported: ["header"],
26
+ }));
27
+ const log = options.logger ?? defaultLogger;
28
+ app.post(MCP_PATH, (c) => handleMcpPost(c, options, log));
29
+ // Stateless — no server-initiated notifications, no session termination.
30
+ // Spec allows 405 for either, as long as `Allow` advertises what IS valid.
31
+ app.get(MCP_PATH, (c) => methodNotAllowed(c));
32
+ app.delete(MCP_PATH, (c) => methodNotAllowed(c));
33
+ app.all(MCP_PATH, (c) => methodNotAllowed(c));
34
+ return app;
35
+ }
36
+ function prmResourceFor(prmUrl) {
37
+ // The `resource` in PRM is the MCP endpoint, not the PRM doc URL itself.
38
+ // Derive it from the PRM URL by replacing the well-known suffix with `/mcp`.
39
+ try {
40
+ const u = new URL(prmUrl);
41
+ u.pathname = MCP_PATH;
42
+ return u.toString();
43
+ }
44
+ catch {
45
+ return prmUrl;
46
+ }
47
+ }
48
+ function methodNotAllowed(_c) {
49
+ return new Response(JSON.stringify({
50
+ jsonrpc: "2.0",
51
+ error: { code: -32000, message: "Method not allowed." },
52
+ id: null,
53
+ }), {
54
+ status: 405,
55
+ headers: { Allow: "POST", "Content-Type": "application/json" },
56
+ });
57
+ }
58
+ async function handleMcpPost(c, options, log) {
59
+ const start = Date.now();
60
+ const protocolVersion = c.req.header("mcp-protocol-version") ?? undefined;
61
+ const userAgent = c.req.header("user-agent") ?? undefined;
62
+ // Peek the body once so we can log the JSON-RPC method/tool. The SDK reads
63
+ // the request body itself, so we re-make a Request with the same body text
64
+ // before forwarding. Body peek is cheap (single small JSON-RPC frame).
65
+ const bodyText = await c.req.raw.text().catch(() => "");
66
+ const peeked = peekRpcBody(bodyText);
67
+ const finalize = (status, extra = {}) => {
68
+ log.log({
69
+ event: "http_request",
70
+ status,
71
+ duration_ms: Date.now() - start,
72
+ ...(peeked.method !== undefined ? { mcp_method: peeked.method } : {}),
73
+ ...(peeked.tool !== undefined ? { tool: peeked.tool } : {}),
74
+ ...(protocolVersion !== undefined ? { mcp_protocol_version: protocolVersion } : {}),
75
+ ...(userAgent !== undefined ? { client_user_agent: userAgent } : {}),
76
+ ...extra,
77
+ });
78
+ };
79
+ const prmUrl = options.protectedResourceMetadataUrl;
80
+ const authCtx = {
81
+ header: (name) => c.req.header(name) ?? null,
82
+ searchParams: new URL(c.req.url).searchParams,
83
+ protectedResourceMetadataUrl: prmUrl,
84
+ };
85
+ const resolution = extractHttpBearer(authCtx);
86
+ if (!resolution.ok) {
87
+ finalize(401);
88
+ return unauthorizedResponse(resolution.message, resolution.wwwAuthenticate);
89
+ }
90
+ let upstreamRequestId = null;
91
+ const server = buildServer({
92
+ apiKey: resolution.apiKey,
93
+ ...(options.baseUrl !== undefined ? { baseUrl: options.baseUrl } : {}),
94
+ ...(options.fetchImpl !== undefined ? { fetchImpl: options.fetchImpl } : {}),
95
+ onUpstreamResponse: ({ requestId }) => {
96
+ // Last upstream call wins — single tool invocation per JSON-RPC frame in
97
+ // practice, so this is the call's request id.
98
+ if (requestId)
99
+ upstreamRequestId = requestId;
100
+ },
101
+ });
102
+ // Stateless mode: `sessionIdGenerator` explicitly undefined disables session
103
+ // tracking entirely. JSON responses (not SSE) because this server never
104
+ // pushes notifications — simpler to reason about and lets us await full
105
+ // completion before releasing the per-request server.
106
+ const transport = new WebStandardStreamableHTTPServerTransport({
107
+ sessionIdGenerator: undefined,
108
+ enableJsonResponse: true,
109
+ });
110
+ // Re-construct the request because we already consumed its body above.
111
+ const forwarded = new Request(c.req.raw.url, {
112
+ method: c.req.raw.method,
113
+ headers: c.req.raw.headers,
114
+ body: bodyText,
115
+ });
116
+ try {
117
+ await server.connect(transport);
118
+ const response = await transport.handleRequest(forwarded);
119
+ await server.close();
120
+ finalize(response.status, upstreamRequestId ? { meertrack_request_id: upstreamRequestId } : {});
121
+ return response;
122
+ }
123
+ catch (err) {
124
+ await server.close().catch(() => { });
125
+ const message = err instanceof Error ? err.message : String(err);
126
+ finalize(500, { error: message, ...(upstreamRequestId ? { meertrack_request_id: upstreamRequestId } : {}) });
127
+ return new Response(JSON.stringify({
128
+ jsonrpc: "2.0",
129
+ error: { code: -32603, message: `Internal error: ${message}` },
130
+ id: null,
131
+ }), { status: 500, headers: { "Content-Type": "application/json" } });
132
+ }
133
+ }
134
+ /**
135
+ * Pull the JSON-RPC `method` and (when applicable) the `params.name` tool name
136
+ * out of a request body. Tolerates malformed bodies — bad input is the SDK's
137
+ * job to reject; logging just records what we can see.
138
+ */
139
+ function peekRpcBody(text) {
140
+ if (!text)
141
+ return {};
142
+ try {
143
+ const parsed = JSON.parse(text);
144
+ const first = Array.isArray(parsed) ? parsed[0] : parsed;
145
+ if (!first || typeof first !== "object")
146
+ return {};
147
+ const method = typeof first.method === "string" ? first.method : undefined;
148
+ const tool = method === "tools/call" && first.params && typeof first.params.name === "string"
149
+ ? first.params.name
150
+ : undefined;
151
+ return {
152
+ ...(method !== undefined ? { method } : {}),
153
+ ...(tool !== undefined ? { tool } : {}),
154
+ };
155
+ }
156
+ catch {
157
+ return {};
158
+ }
159
+ }
160
+ function unauthorizedResponse(message, wwwAuthenticate) {
161
+ return new Response(JSON.stringify({ error: { code: "unauthorized", message } }), {
162
+ status: 401,
163
+ headers: {
164
+ "Content-Type": "application/json",
165
+ "WWW-Authenticate": wwwAuthenticate,
166
+ },
167
+ });
168
+ }
169
+ /**
170
+ * Resolve the PRM URL from config + the incoming request. Used by the
171
+ * entrypoint when users don't override the metadata URL explicitly: derive it
172
+ * from the first request's `Host`. For the production Fly deploy, this config
173
+ * is set at startup via `MEERTRACK_MCP_PRM_URL` to the public HTTPS URL.
174
+ */
175
+ export function defaultProtectedResourceMetadataUrl(host, protocol = "https") {
176
+ return `${protocol}://${host}${PRM_PATH}`;
177
+ }
178
+ export { buildWwwAuthenticateHeader };
179
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type BuildServerOptions } from "../server.js";
2
+ /**
3
+ * stdio transport: read JSON-RPC frames from process.stdin, write responses to
4
+ * process.stdout. stdout is a protocol channel — every diagnostic must go to
5
+ * stderr so we don't corrupt the MCP framing. The logger writes single-line
6
+ * JSON to stderr for parity with the HTTP transport, with the same redaction.
7
+ *
8
+ * Owns the process lifetime: returns when the transport closes (client
9
+ * disconnected stdin) or a fatal signal fires.
10
+ */
11
+ export declare function runStdio(opts: BuildServerOptions): Promise<void>;
12
+ //# sourceMappingURL=stdio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIpE;;;;;;;;GAQG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBtE"}
@@ -0,0 +1,35 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { buildServer } from "../server.js";
3
+ import { logger } from "../logger.js";
4
+ import { VERSION } from "../version.js";
5
+ /**
6
+ * stdio transport: read JSON-RPC frames from process.stdin, write responses to
7
+ * process.stdout. stdout is a protocol channel — every diagnostic must go to
8
+ * stderr so we don't corrupt the MCP framing. The logger writes single-line
9
+ * JSON to stderr for parity with the HTTP transport, with the same redaction.
10
+ *
11
+ * Owns the process lifetime: returns when the transport closes (client
12
+ * disconnected stdin) or a fatal signal fires.
13
+ */
14
+ export async function runStdio(opts) {
15
+ const server = buildServer(opts);
16
+ const transport = new StdioServerTransport();
17
+ const shutdown = async (signal) => {
18
+ logger.log({ event: "stdio_shutdown", signal });
19
+ try {
20
+ await server.close();
21
+ }
22
+ catch (err) {
23
+ logger.log({
24
+ event: "stdio_shutdown_error",
25
+ message: err instanceof Error ? err.message : String(err),
26
+ });
27
+ }
28
+ process.exit(0);
29
+ };
30
+ process.once("SIGINT", () => void shutdown("SIGINT"));
31
+ process.once("SIGTERM", () => void shutdown("SIGTERM"));
32
+ await server.connect(transport);
33
+ logger.log({ event: "stdio_ready", version: VERSION });
34
+ }
35
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAwB;IACrD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,QAAQ,GAAG,KAAK,EAAE,MAAsB,EAAiB,EAAE;QAC/D,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,CAAC;gBACT,KAAK,EAAE,sBAAsB;gBAC7B,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAExD,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AACzD,CAAC"}