kojee-mcp 0.1.3 → 0.2.1

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/README.md CHANGED
@@ -6,7 +6,7 @@ kojee-mcp is a local MCP proxy that lets any MCP-capable agent use Kojee-managed
6
6
 
7
7
  1. **Get a gateway token** from the [Kojee dashboard](https://kojee.ai).
8
8
  2. **Add to your MCP config** (see examples below).
9
- 3. **Tools appear automatically** -- the proxy discovers and exposes all tools your token has access to.
9
+ 3. **Tools appear automatically** -- all Kojee tools your token has access to are exposed directly (e.g. `gmail_send_email`, `github_list_repos`, `calendar_create_event`). Agents call them like any native MCP tool — no discovery step, no wrapper, no indirection.
10
10
 
11
11
  ## MCP Config Examples
12
12
 
@@ -517,104 +517,56 @@ function sleep(ms) {
517
517
  }
518
518
 
519
519
  // src/tool-registry.ts
520
- var BUILTIN_TOOL_NAMES = /* @__PURE__ */ new Set([
521
- "kojee_check_approval",
522
- "kojee_revoke_request",
523
- "kojee_send_feedback"
524
- ]);
525
520
  var ToolRegistry = class {
526
521
  constructor(gateway) {
527
522
  this.gateway = gateway;
528
523
  }
529
524
  gateway;
530
- /** Connector ID connector info with tool list */
531
- connectors = /* @__PURE__ */ new Map();
532
- /** All tool names (flat) for validation */
533
- allToolNames = /* @__PURE__ */ new Set();
525
+ /** Flat map: tool name full tool definition */
526
+ tools = /* @__PURE__ */ new Map();
534
527
  /**
535
- * Fetch the lean tool list from the gateway and group by connector.
528
+ * Fetch all tools with full schemas from the gateway in a single RPC call.
536
529
  */
537
530
  async discoverTools() {
538
- console.error("[tools] Fetching lean tool list from gateway...");
539
- const listResult = await this.gateway.sendRpc("tools/list", {});
540
- const toolList = listResult?.tools;
531
+ console.error("[tools] Fetching tools with full schemas from gateway...");
532
+ const result = await this.gateway.sendRpc("tools/list", {
533
+ include_schema: true
534
+ });
535
+ const maybeError = result;
536
+ if (maybeError.isError) {
537
+ const msg = maybeError.content?.[0]?.text ?? "unknown error";
538
+ throw new Error(`Gateway rejected tools/list: ${msg}`);
539
+ }
540
+ const toolList = result?.tools;
541
541
  if (!toolList || !Array.isArray(toolList)) {
542
542
  console.error("[tools] No tools returned from gateway");
543
543
  return;
544
544
  }
545
545
  for (const tool of toolList) {
546
- this.allToolNames.add(tool.name);
547
- if (BUILTIN_TOOL_NAMES.has(tool.name)) continue;
548
- const connector = tool._connector_id ?? (tool.name.includes("_") ? tool.name.substring(0, tool.name.indexOf("_")) : null);
549
- if (!connector) {
550
- console.error(`[tools] Skipping tool with no connector: ${tool.name}`);
551
- continue;
546
+ if (this.tools.has(tool.name)) {
547
+ console.error(`[tools] Warning: duplicate tool name "${tool.name}" \u2014 overwriting`);
552
548
  }
553
- let info = this.connectors.get(connector);
554
- if (!info) {
555
- info = { id: connector, tools: [] };
556
- this.connectors.set(connector, info);
557
- }
558
- info.tools.push({ name: tool.name, description: tool.description });
559
- }
560
- console.error(
561
- `[tools] Discovered ${this.allToolNames.size} tools across ${this.connectors.size} connectors`
562
- );
563
- }
564
- /**
565
- * Get the list of connector meta-tools to register with the MCP server.
566
- * Each connector becomes a tool like "kojee_gmail" whose description
567
- * lists its available tools.
568
- */
569
- getConnectorTools() {
570
- const tools = [];
571
- for (const [connectorId, info] of this.connectors) {
572
- const toolNames = info.tools.map((t) => t.name).join(", ");
573
- tools.push({
574
- name: connectorId,
575
- description: `${connectorId} tools available via Kojee (${info.tools.length} tools: ${toolNames}). Call this tool to see descriptions and details for each.`,
576
- inputSchema: { type: "object", properties: {} }
577
- });
578
- }
579
- return tools;
580
- }
581
- /**
582
- * Get the detailed tool list for a specific connector.
583
- */
584
- getConnectorToolList(connectorId) {
585
- const info = this.connectors.get(connectorId);
586
- if (!info) {
587
- return `No connector '${connectorId}' found. Available: ${Array.from(this.connectors.keys()).join(", ")}`;
549
+ this.tools.set(tool.name, tool);
588
550
  }
589
- const lines = info.tools.map((t) => `- **${t.name}**: ${t.description}`);
590
- return `## ${connectorId} tools
591
-
592
- ${lines.join("\n")}
593
-
594
- Use kojee_get_tool_schema to get the full input schema, then kojee_call_tool to execute.`;
551
+ console.error(`[tools] Registered ${this.tools.size} tools from gateway`);
595
552
  }
596
553
  /**
597
- * Get full schemas for specific tools via tools/get_schema.
554
+ * Return all registered tools for the MCP ListTools response.
598
555
  */
599
- async getToolSchemas(names) {
600
- const result = await this.gateway.sendRpc("tools/get_schema", { names });
601
- const response = result;
602
- if (response.not_found && response.not_found.length > 0) {
603
- console.error(`[tools] Schemas not found for: ${response.not_found.join(", ")}`);
604
- }
605
- return response.tools ?? [];
556
+ getAllTools() {
557
+ return Array.from(this.tools.values());
606
558
  }
607
559
  /**
608
560
  * Call a tool through the gateway.
609
561
  */
610
562
  async callTool(name, args) {
611
- if (!this.allToolNames.has(name)) {
612
- const available = Array.from(this.connectors.keys()).map((c) => `kojee_${c}`).join(", ");
563
+ if (!this.tools.has(name)) {
564
+ const available = Array.from(this.tools.keys()).slice(0, 10).join(", ");
613
565
  return {
614
566
  content: [
615
567
  {
616
568
  type: "text",
617
- text: `Tool '${name}' not found. Use one of the connector tools (${available}) to discover available tools.`
569
+ text: `Tool '${name}' not found. Some available tools: ${available}${this.tools.size > 10 ? ", ..." : ""}`
618
570
  }
619
571
  ],
620
572
  isError: true
@@ -625,13 +577,9 @@ Use kojee_get_tool_schema to get the full input schema, then kojee_call_tool to
625
577
  arguments: args
626
578
  });
627
579
  }
628
- /** List of connector IDs. */
629
- get connectorIds() {
630
- return Array.from(this.connectors.keys());
631
- }
632
- /** Total number of discovered tools. */
580
+ /** Total number of registered tools. */
633
581
  get toolCount() {
634
- return this.allToolNames.size;
582
+ return this.tools.size;
635
583
  }
636
584
  };
637
585
 
@@ -642,85 +590,11 @@ import {
642
590
  ListToolsRequestSchema,
643
591
  CallToolRequestSchema
644
592
  } from "@modelcontextprotocol/sdk/types.js";
645
- var UTILITY_TOOL_NAMES = /* @__PURE__ */ new Set([
646
- "get_tool_schema",
647
- "call_tool",
648
- "check_approval",
649
- "revoke_request"
650
- ]);
651
- var UTILITY_TOOLS = [
652
- {
653
- name: "get_tool_schema",
654
- description: "Get the full input schema for one or more Kojee tools. Call this before call_tool to know the exact parameters required.",
655
- inputSchema: {
656
- type: "object",
657
- properties: {
658
- names: {
659
- type: "array",
660
- items: { type: "string" },
661
- description: 'Tool names to get schemas for (e.g. ["gmail_send_email", "github_list_repos"])'
662
- }
663
- },
664
- required: ["names"]
665
- }
666
- },
667
- {
668
- name: "call_tool",
669
- description: "Call a Kojee tool by name with the specified arguments. Use the connector tools (e.g. kojee_gmail) to discover tools, then get_tool_schema to get parameters, then this to execute.",
670
- inputSchema: {
671
- type: "object",
672
- properties: {
673
- name: {
674
- type: "string",
675
- description: 'The tool name (e.g. "gmail_send_email")'
676
- },
677
- arguments: {
678
- type: "object",
679
- description: "The tool arguments matching the tool's input schema",
680
- additionalProperties: true
681
- }
682
- },
683
- required: ["name"]
684
- }
685
- },
686
- {
687
- name: "check_approval",
688
- description: "Check the status of a pending approval request. Use this after a tool call returns 'require_approval' to poll whether the user has approved or denied.",
689
- inputSchema: {
690
- type: "object",
691
- properties: {
692
- approval_id: {
693
- type: "string",
694
- description: "The approval ID returned when a tool call requires approval"
695
- }
696
- },
697
- required: ["approval_id"]
698
- }
699
- },
700
- {
701
- name: "revoke_request",
702
- description: "Revoke/cancel a pending approval request you no longer need.",
703
- inputSchema: {
704
- type: "object",
705
- properties: {
706
- approval_id: {
707
- type: "string",
708
- description: "The approval ID to revoke"
709
- },
710
- reason: {
711
- type: "string",
712
- description: "Optional reason for revoking"
713
- }
714
- },
715
- required: ["approval_id"]
716
- }
717
- }
718
- ];
719
593
  function createMcpServer(registry) {
720
594
  const server = new Server(
721
595
  {
722
596
  name: "kojee-mcp",
723
- version: "0.1.1"
597
+ version: "0.2.0"
724
598
  },
725
599
  {
726
600
  capabilities: {
@@ -729,69 +603,21 @@ function createMcpServer(registry) {
729
603
  }
730
604
  );
731
605
  server.setRequestHandler(ListToolsRequestSchema, async () => {
732
- const connectorTools = registry.getConnectorTools();
733
- return { tools: [...connectorTools, ...UTILITY_TOOLS] };
606
+ const tools = registry.getAllTools().map((t) => ({
607
+ name: t.name,
608
+ description: t.description,
609
+ inputSchema: t.inputSchema
610
+ }));
611
+ return { tools };
734
612
  });
735
613
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
736
614
  const { name, arguments: args } = request.params;
737
- if (!UTILITY_TOOL_NAMES.has(name)) {
738
- const toolList = registry.getConnectorToolList(name);
739
- return {
740
- content: [{ type: "text", text: toolList }],
741
- isError: false
742
- };
743
- }
744
- switch (name) {
745
- case "get_tool_schema": {
746
- const names = args?.names ?? [];
747
- if (names.length === 0) {
748
- return {
749
- content: [{ type: "text", text: "Provide tool names in the 'names' array." }],
750
- isError: true
751
- };
752
- }
753
- const schemas = await registry.getToolSchemas(names);
754
- return {
755
- content: [{ type: "text", text: JSON.stringify(schemas, null, 2) }],
756
- isError: false
757
- };
758
- }
759
- case "call_tool": {
760
- const toolName = args?.name;
761
- if (!toolName) {
762
- return {
763
- content: [{ type: "text", text: "Provide the tool name in the 'name' field." }],
764
- isError: true
765
- };
766
- }
767
- const toolArgs = args?.arguments ?? {};
768
- const rawResult = await registry.callTool(toolName, toolArgs);
769
- const result = translateToolCallResult(rawResult);
770
- return {
771
- content: result.content,
772
- isError: result.isError
773
- };
774
- }
775
- case "check_approval":
776
- case "revoke_request": {
777
- const rawResult = await registry.callTool(name, args ?? {});
778
- const result = translateToolCallResult(rawResult);
779
- return {
780
- content: result.content,
781
- isError: result.isError
782
- };
783
- }
784
- default:
785
- return {
786
- content: [
787
- {
788
- type: "text",
789
- text: `Unknown tool '${name}'. Use one of the connector tools or utility tools.`
790
- }
791
- ],
792
- isError: true
793
- };
794
- }
615
+ const rawResult = await registry.callTool(name, args ?? {});
616
+ const result = translateToolCallResult(rawResult);
617
+ return {
618
+ content: result.content,
619
+ isError: result.isError
620
+ };
795
621
  });
796
622
  return server;
797
623
  }
@@ -827,6 +653,10 @@ async function startProxy(config) {
827
653
  `[kojee-mcp] Ready \u2014 ${registry.toolCount} tools available from ${config.url}`
828
654
  );
829
655
  const server = createMcpServer(registry);
656
+ process.stdin.on("end", () => {
657
+ console.error("[kojee-mcp] stdin closed, exiting");
658
+ process.exit(0);
659
+ });
830
660
  await startMcpServer(server);
831
661
  }
832
662
 
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startProxy
4
- } from "./chunk-AYJ6WN2K.js";
4
+ } from "./chunk-RNKJONY3.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { Command } from "commander";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  startProxy
3
- } from "./chunk-AYJ6WN2K.js";
3
+ } from "./chunk-RNKJONY3.js";
4
4
  export {
5
5
  startProxy
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kojee-mcp",
3
- "version": "0.1.3",
3
+ "version": "0.2.1",
4
4
  "description": "Local MCP proxy for Kojee — handles DPoP auth, tool discovery, and governance transparently",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",