@pyxmate/memory 1.0.1 → 1.1.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.
@@ -563,9 +563,91 @@ function createReadCredentials(providerFactory) {
563
563
  };
564
564
  }
565
565
 
566
+ // src/mcp/proxy-server.ts
567
+ import { Client as McpClient } from "@modelcontextprotocol/sdk/client/index.js";
568
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
569
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
570
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
571
+ import {
572
+ CallToolRequestSchema,
573
+ GetPromptRequestSchema,
574
+ ListPromptsRequestSchema,
575
+ ListToolsRequestSchema
576
+ } from "@modelcontextprotocol/sdk/types.js";
577
+ var REMOTE_MCP_PATH = "/mcp";
578
+ function createProxyServer(client, version) {
579
+ const caps = client.getServerCapabilities();
580
+ const server = new Server(client.getServerVersion() ?? { name: "pyx-memory", version }, {
581
+ capabilities: {
582
+ // Advertise the PRESENCE of tools/prompts, but NOT their `listChanged`
583
+ // sub-capability: this proxy does not relay the remote's list_changed
584
+ // notifications, so claiming listChanged would be a capability the host
585
+ // could rely on but we never honor (Codex: keep the proxy transparent).
586
+ ...caps?.tools ? { tools: {} } : {},
587
+ ...caps?.prompts ? { prompts: {} } : {}
588
+ },
589
+ instructions: client.getInstructions()
590
+ });
591
+ if (caps?.tools) {
592
+ server.setRequestHandler(
593
+ ListToolsRequestSchema,
594
+ (req) => client.listTools(req.params)
595
+ );
596
+ server.setRequestHandler(
597
+ CallToolRequestSchema,
598
+ (req) => client.callTool(req.params)
599
+ );
600
+ }
601
+ if (caps?.prompts) {
602
+ server.setRequestHandler(
603
+ ListPromptsRequestSchema,
604
+ (req) => client.listPrompts(req.params)
605
+ );
606
+ server.setRequestHandler(
607
+ GetPromptRequestSchema,
608
+ (req) => client.getPrompt(req.params)
609
+ );
610
+ }
611
+ return server;
612
+ }
613
+ async function runMcpProxyServer(opts) {
614
+ const version = opts.version ?? (true ? "1.1.0" : "0.0.0-dev");
615
+ const read = await opts.readCredentials();
616
+ if (!read.ok) {
617
+ const text = read.result.content.map((c) => c.type === "text" ? c.text : "").join(" ").trim();
618
+ throw new Error(text || "pyx-memory credentials are unavailable. Run: pyx-mem login");
619
+ }
620
+ const { endpoint, apiKey } = read.credentials;
621
+ const url = new URL(`${endpoint.replace(/\/+$/, "")}${REMOTE_MCP_PATH}`);
622
+ const client = new McpClient({ name: "pyx-mem-proxy", version }, { capabilities: {} });
623
+ const clientTransport = new StreamableHTTPClientTransport(url, {
624
+ requestInit: { headers: { Authorization: `Bearer ${apiKey}` } }
625
+ });
626
+ try {
627
+ await client.connect(clientTransport);
628
+ } catch (err) {
629
+ const msg = err instanceof Error ? err.message : String(err);
630
+ throw new Error(
631
+ `Could not reach the pyx-memory remote MCP at ${url.href}: ${msg}. Verify the endpoint and key with \`pyx-mem doctor\`, or run the bundled server with \`pyx-mem mcp\`.`
632
+ );
633
+ }
634
+ try {
635
+ const server = createProxyServer(client, version);
636
+ const transport = new StdioServerTransport();
637
+ const closed = new Promise((resolve3) => {
638
+ transport.onclose = () => resolve3();
639
+ });
640
+ await server.connect(transport);
641
+ await closed;
642
+ } finally {
643
+ await client.close().catch(() => {
644
+ });
645
+ }
646
+ }
647
+
566
648
  // src/mcp/server.ts
567
649
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
568
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
650
+ import { StdioServerTransport as StdioServerTransport2 } from "@modelcontextprotocol/sdk/server/stdio.js";
569
651
 
570
652
  // src/mcp/prompts/index.ts
571
653
  import { z } from "zod";
@@ -1377,7 +1459,7 @@ var ALL_TOOL_NAMES = ALL_TOOLS.map((t) => t.name);
1377
1459
  // src/mcp/server.ts
1378
1460
  async function runMcpServer(opts) {
1379
1461
  const fetchImpl = opts.fetchImpl ?? fetch;
1380
- const version = opts.version ?? (true ? "1.0.1" : "0.0.0-dev");
1462
+ const version = opts.version ?? (true ? "1.1.0" : "0.0.0-dev");
1381
1463
  const server = new McpServer(
1382
1464
  { name: "pyx-memory", version },
1383
1465
  { instructions: PYX_MEMORY_INSTRUCTIONS, capabilities: { tools: {}, prompts: {} } }
@@ -1396,7 +1478,7 @@ async function runMcpServer(opts) {
1396
1478
  for (const prompt of ALL_PROMPTS) {
1397
1479
  prompt.register(server);
1398
1480
  }
1399
- const transport = new StdioServerTransport();
1481
+ const transport = new StdioServerTransport2();
1400
1482
  const closed = new Promise((resolve3) => {
1401
1483
  transport.onclose = () => resolve3();
1402
1484
  });
@@ -1405,14 +1487,15 @@ async function runMcpServer(opts) {
1405
1487
  }
1406
1488
 
1407
1489
  // src/cli/commands/mcp.ts
1408
- async function mcpCommand() {
1490
+ async function mcpCommand(opts = {}) {
1409
1491
  const readCredentials = createReadCredentials(() => getDefaultKeychain());
1410
1492
  const onStdinEnd = new Promise((resolve3) => {
1411
1493
  process.stdin.once("end", resolve3);
1412
1494
  process.stdin.once("close", resolve3);
1413
1495
  });
1414
1496
  try {
1415
- await Promise.race([runMcpServer({ readCredentials }), onStdinEnd]);
1497
+ const run = opts.remote ? runMcpProxyServer({ readCredentials }) : runMcpServer({ readCredentials });
1498
+ await Promise.race([run, onStdinEnd]);
1416
1499
  return EXIT.OK;
1417
1500
  } catch (err) {
1418
1501
  process.stderr.write(`Internal error: ${err instanceof Error ? err.message : String(err)}
@@ -2101,7 +2184,9 @@ Commands:
2101
2184
  logout Delete stored pyx-memory credentials.
2102
2185
  doctor [--json] Diagnose keychain, credentials, backend, MCP startup.
2103
2186
  scaffold [--name <dir>] Generate Docker, env, SDK, and memory design-guide starter files.
2104
- mcp Start stdio MCP server.
2187
+ mcp [--remote] Start stdio MCP server. --remote proxies to the hosted
2188
+ server so tools + instructions stay server-owned
2189
+ (zero-touch updates; key stays in the keychain).
2105
2190
  mcp install <target> [--scope user|local|project]
2106
2191
  Install pyx-memory MCP config for your AI agent.
2107
2192
  Targets: claude-code, codex, cursor, cline, continue, windsurf, gemini-cli, pi, oh-my-pi, openclaw, hermes.
@@ -2183,7 +2268,7 @@ function runMcpInstall(target, scope) {
2183
2268
  return handler({ scope });
2184
2269
  }
2185
2270
  function runMcpCommand(parsed) {
2186
- if (parsed.subcommand === void 0) return mcpCommand();
2271
+ if (parsed.subcommand === void 0) return mcpCommand({ remote: parsed.flags.remote === true });
2187
2272
  if (parsed.subcommand === "install") {
2188
2273
  const target = parsed.positional[0];
2189
2274
  const scope = typeof parsed.flags.scope === "string" ? parsed.flags.scope : void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyxmate/memory",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "SDK for pyx-memory — Memory as a Service for AI agents",
6
6
  "license": "MIT",