@telora/mcp-products 0.21.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.
Files changed (63) hide show
  1. package/README.md +276 -0
  2. package/dist/cli/init.d.ts +2 -0
  3. package/dist/cli/init.js +94 -0
  4. package/dist/cli/init.js.map +1 -0
  5. package/dist/handlers/agentHandlers.d.ts +3 -0
  6. package/dist/handlers/agentHandlers.js +97 -0
  7. package/dist/handlers/agentHandlers.js.map +1 -0
  8. package/dist/handlers/connectorHandlers.d.ts +3 -0
  9. package/dist/handlers/connectorHandlers.js +401 -0
  10. package/dist/handlers/connectorHandlers.js.map +1 -0
  11. package/dist/handlers/contextHandlers.d.ts +8 -0
  12. package/dist/handlers/contextHandlers.js +169 -0
  13. package/dist/handlers/contextHandlers.js.map +1 -0
  14. package/dist/handlers/deliveryHandlers.d.ts +3 -0
  15. package/dist/handlers/deliveryHandlers.js +122 -0
  16. package/dist/handlers/deliveryHandlers.js.map +1 -0
  17. package/dist/handlers/deploymentProfileHandlers.d.ts +3 -0
  18. package/dist/handlers/deploymentProfileHandlers.js +104 -0
  19. package/dist/handlers/deploymentProfileHandlers.js.map +1 -0
  20. package/dist/handlers/discoverHandler.d.ts +23 -0
  21. package/dist/handlers/discoverHandler.js +83 -0
  22. package/dist/handlers/discoverHandler.js.map +1 -0
  23. package/dist/handlers/factoryHandlers.d.ts +3 -0
  24. package/dist/handlers/factoryHandlers.js +484 -0
  25. package/dist/handlers/factoryHandlers.js.map +1 -0
  26. package/dist/handlers/ideaHandlers.d.ts +3 -0
  27. package/dist/handlers/ideaHandlers.js +245 -0
  28. package/dist/handlers/ideaHandlers.js.map +1 -0
  29. package/dist/handlers/index.d.ts +15 -0
  30. package/dist/handlers/index.js +19 -0
  31. package/dist/handlers/index.js.map +1 -0
  32. package/dist/handlers/infrastructureHandlers.d.ts +3 -0
  33. package/dist/handlers/infrastructureHandlers.js +335 -0
  34. package/dist/handlers/infrastructureHandlers.js.map +1 -0
  35. package/dist/handlers/issueHandlers.d.ts +3 -0
  36. package/dist/handlers/issueHandlers.js +94 -0
  37. package/dist/handlers/issueHandlers.js.map +1 -0
  38. package/dist/handlers/okrHandlers.d.ts +3 -0
  39. package/dist/handlers/okrHandlers.js +194 -0
  40. package/dist/handlers/okrHandlers.js.map +1 -0
  41. package/dist/handlers/playbookHandlers.d.ts +3 -0
  42. package/dist/handlers/playbookHandlers.js +93 -0
  43. package/dist/handlers/playbookHandlers.js.map +1 -0
  44. package/dist/handlers/productHandlers.d.ts +3 -0
  45. package/dist/handlers/productHandlers.js +129 -0
  46. package/dist/handlers/productHandlers.js.map +1 -0
  47. package/dist/handlers/reportHandlers.d.ts +3 -0
  48. package/dist/handlers/reportHandlers.js +59 -0
  49. package/dist/handlers/reportHandlers.js.map +1 -0
  50. package/dist/handlers/strategyHandlers.d.ts +3 -0
  51. package/dist/handlers/strategyHandlers.js +116 -0
  52. package/dist/handlers/strategyHandlers.js.map +1 -0
  53. package/dist/handlers/workflowHandlers.d.ts +3 -0
  54. package/dist/handlers/workflowHandlers.js +93 -0
  55. package/dist/handlers/workflowHandlers.js.map +1 -0
  56. package/dist/index.d.ts +2 -0
  57. package/dist/index.js +284 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/shared.d.ts +77 -0
  60. package/dist/shared.js +147 -0
  61. package/dist/shared.js.map +1 -0
  62. package/package.json +47 -0
  63. package/scripts/postinstall.js +96 -0
package/dist/shared.js ADDED
@@ -0,0 +1,147 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Shared types, credential loading, and API client used by all handler modules
3
+ // ---------------------------------------------------------------------------
4
+ // ---------------------------------------------------------------------------
5
+ // Credential loading -- env vars only
6
+ // ---------------------------------------------------------------------------
7
+ export function loadCredentials() {
8
+ // Support both new TELORA_TRACKER_ID (profile-based UUID) and legacy TELORA_ACCESS_TOKEN
9
+ const accessToken = process.env.TELORA_TRACKER_ID || process.env.TELORA_ACCESS_TOKEN;
10
+ if (!process.env.TELORA_TRACKER_ID && process.env.TELORA_ACCESS_TOKEN) {
11
+ console.error("[telora-products] Warning: TELORA_ACCESS_TOKEN is deprecated. Use TELORA_TRACKER_ID instead.");
12
+ }
13
+ const teloraUrl = process.env.TELORA_URL;
14
+ if (accessToken && teloraUrl) {
15
+ return { accessToken, teloraUrl };
16
+ }
17
+ throw new Error("MCP server not configured. Run: npx @telora/mcp-products init");
18
+ }
19
+ // ---------------------------------------------------------------------------
20
+ // API client
21
+ // ---------------------------------------------------------------------------
22
+ export async function callProductApi(creds, body) {
23
+ const url = `${creds.teloraUrl}/functions/v1/product-api`;
24
+ const response = await fetch(url, {
25
+ method: "POST",
26
+ headers: {
27
+ Authorization: `Bearer ${creds.accessToken}`,
28
+ "Content-Type": "application/json",
29
+ },
30
+ body: JSON.stringify(body),
31
+ });
32
+ const data = await response.json();
33
+ if (!response.ok || !data.success) {
34
+ throw new Error(data.error || `API error (${response.status})`);
35
+ }
36
+ return data;
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Helper to build MCP tool responses
40
+ // ---------------------------------------------------------------------------
41
+ export function successResult(data) {
42
+ return {
43
+ content: [
44
+ {
45
+ type: "text",
46
+ text: typeof data === "string" ? data : JSON.stringify(data, null, 2),
47
+ },
48
+ ],
49
+ };
50
+ }
51
+ export function errorResult(err) {
52
+ return {
53
+ content: [{ type: "text", text: err.message }],
54
+ isError: true,
55
+ };
56
+ }
57
+ export function validationError(message) {
58
+ return {
59
+ content: [{ type: "text", text: message }],
60
+ isError: true,
61
+ };
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Compact entity helper -- minimize token usage in mutation responses
65
+ // ---------------------------------------------------------------------------
66
+ /**
67
+ * Strip an entity response to only the ID + fields the caller requested.
68
+ * Used by create/update handlers to minimize token usage in agent responses.
69
+ */
70
+ export function compactEntity(entity, requestedFields, returnFull) {
71
+ if (returnFull)
72
+ return entity;
73
+ const compact = { id: entity.id };
74
+ for (const key of requestedFields) {
75
+ if (key in entity)
76
+ compact[key] = entity[key];
77
+ }
78
+ return compact;
79
+ }
80
+ /**
81
+ * Build a fields object from params, only including defined values.
82
+ * Replaces the repetitive `if (x !== undefined) fields.x = x` pattern.
83
+ *
84
+ * @param params - Object with all tool parameters
85
+ * @param fieldNames - Names of fields to include (defaults to all params)
86
+ * @param required - Names of required fields to always include
87
+ *
88
+ * @example
89
+ * // Before:
90
+ * const fields: Record<string, unknown> = {};
91
+ * if (name !== undefined) fields.name = name;
92
+ * if (description !== undefined) fields.description = description;
93
+ * if (status !== undefined) fields.status = status;
94
+ *
95
+ * // After:
96
+ * const fields = buildFields(params, ['name', 'description', 'status']);
97
+ */
98
+ export function buildFields(params, fieldNames, required) {
99
+ const fields = {};
100
+ const keys = fieldNames ?? Object.keys(params);
101
+ for (const key of keys) {
102
+ if (params[key] !== undefined) {
103
+ fields[key] = params[key];
104
+ }
105
+ }
106
+ // Always include required fields even if undefined
107
+ if (required) {
108
+ for (const key of required) {
109
+ if (!(key in fields) && key in params) {
110
+ fields[key] = params[key];
111
+ }
112
+ }
113
+ }
114
+ return fields;
115
+ }
116
+ /**
117
+ * Wrap an async handler with standard try/catch error handling.
118
+ * Replaces the repetitive try { ... } catch (err) { return errorResult(err); } pattern.
119
+ *
120
+ * @example
121
+ * // Before:
122
+ * async (params) => {
123
+ * try {
124
+ * const result = await callProductApi(getCreds(), { action: "create", ... });
125
+ * return successResult(result.product);
126
+ * } catch (err) {
127
+ * return errorResult(err);
128
+ * }
129
+ * }
130
+ *
131
+ * // After:
132
+ * wrapHandler(async (params) => {
133
+ * const result = await callProductApi(getCreds(), { action: "create", ... });
134
+ * return successResult(result.product);
135
+ * })
136
+ */
137
+ export function wrapHandler(handler) {
138
+ return async (params) => {
139
+ try {
140
+ return await handler(params);
141
+ }
142
+ catch (err) {
143
+ return errorResult(err);
144
+ }
145
+ };
146
+ }
147
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@telora/mcp-products",
3
+ "version": "0.21.1",
4
+ "description": "MCP server exposing Telora product operations to Claude Code",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "telora-mcp-products": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "scripts",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "postinstall": "node scripts/postinstall.js || true",
17
+ "build": "tsc",
18
+ "start": "node dist/index.js",
19
+ "dev": "npx tsx src/index.ts",
20
+ "lint": "eslint .",
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "echo 'No tests implemented - MCP server is manually tested via Claude Code integration'",
23
+ "clean": "rm -rf dist",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public",
28
+ "registry": "https://registry.npmjs.org/"
29
+ },
30
+ "engines": {
31
+ "node": ">=18.0.0"
32
+ },
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "ssh://git@10.1.1.250:3122/syntelyos/telora.git",
37
+ "directory": "mcp/telora-products"
38
+ },
39
+ "dependencies": {
40
+ "@modelcontextprotocol/sdk": "^1.12.1",
41
+ "zod": "^4.3.6"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^22.13.1",
45
+ "typescript": "^5.7.3"
46
+ }
47
+ }
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ // ---------------------------------------------------------------------------
3
+ // postinstall: wire up Claude Code hooks if telora-ai binaries are on PATH
4
+ // ---------------------------------------------------------------------------
5
+ // Runs after `npm install -g @telora/mcp-products`. If telora-ai-hook and
6
+ // telora-ai-human-hook are available, configures them in ~/.claude/settings.json.
7
+ // Never fails the install -- all errors are swallowed silently.
8
+ // ---------------------------------------------------------------------------
9
+
10
+ "use strict";
11
+
12
+ const { execSync } = require("child_process");
13
+ const { readFileSync, writeFileSync, mkdirSync, existsSync } = require("fs");
14
+ const { join } = require("path");
15
+ const { homedir } = require("os");
16
+
17
+ try {
18
+ // Resolve full paths to hook binaries (bare names may not work in Claude Code subprocesses)
19
+ const resolveHook = (name) => {
20
+ try {
21
+ return execSync(`which ${name}`, { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
22
+ } catch {
23
+ return null;
24
+ }
25
+ };
26
+
27
+ const hookPath = resolveHook("telora-ai-hook");
28
+ const humanHookPath = resolveHook("telora-ai-human-hook");
29
+
30
+ if (!hookPath || !humanHookPath) {
31
+ // telora-ai not installed -- skip silently
32
+ process.exit(0);
33
+ }
34
+
35
+ // Read or create ~/.claude/settings.json
36
+ const claudeDir = join(homedir(), ".claude");
37
+ const settingsPath = join(claudeDir, "settings.json");
38
+
39
+ let settings = {};
40
+ if (existsSync(settingsPath)) {
41
+ try {
42
+ settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
43
+ } catch {
44
+ // Malformed JSON -- start fresh but preserve file
45
+ settings = {};
46
+ }
47
+ }
48
+
49
+ if (!settings.hooks || typeof settings.hooks !== "object") {
50
+ settings.hooks = {};
51
+ }
52
+
53
+ // Ensure hook arrays exist
54
+ if (!Array.isArray(settings.hooks.PostToolUse)) {
55
+ settings.hooks.PostToolUse = [];
56
+ }
57
+ if (!Array.isArray(settings.hooks.UserPromptSubmit)) {
58
+ settings.hooks.UserPromptSubmit = [];
59
+ }
60
+
61
+ // Check if a telora hook is already configured in a rules array.
62
+ // Each entry has { matcher, hooks: [{ type, command }] } structure.
63
+ // Also updates the path if the binary moved.
64
+ const ensureHook = (rulesArr, binaryName, fullPath) => {
65
+ let found = false;
66
+ for (const rule of rulesArr) {
67
+ for (const h of (rule && rule.hooks) || []) {
68
+ const cmd = h.command || "";
69
+ if (cmd.includes(binaryName)) {
70
+ if (cmd !== fullPath) {
71
+ h.command = fullPath;
72
+ }
73
+ found = true;
74
+ }
75
+ }
76
+ }
77
+ if (!found) {
78
+ rulesArr.push({
79
+ matcher: "",
80
+ hooks: [{ type: "command", command: fullPath }],
81
+ });
82
+ }
83
+ };
84
+
85
+ ensureHook(settings.hooks.PostToolUse, "telora-ai-hook", hookPath);
86
+ ensureHook(settings.hooks.UserPromptSubmit, "telora-ai-human-hook", humanHookPath);
87
+
88
+ // Write back
89
+ if (!existsSync(claudeDir)) {
90
+ mkdirSync(claudeDir, { recursive: true });
91
+ }
92
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
93
+ } catch {
94
+ // Never fail the install
95
+ process.exit(0);
96
+ }