@linkedapi/mcp 1.0.0 → 1.0.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 (83) hide show
  1. package/README.md +9 -0
  2. package/dist/index.js +42 -9
  3. package/dist/index.js.map +1 -1
  4. package/dist/linked-api-server.d.ts +7 -4
  5. package/dist/linked-api-server.d.ts.map +1 -1
  6. package/dist/linked-api-server.js +46 -14
  7. package/dist/linked-api-server.js.map +1 -1
  8. package/dist/linked-api-tools.d.ts +18 -4
  9. package/dist/linked-api-tools.d.ts.map +1 -1
  10. package/dist/linked-api-tools.js +28 -28
  11. package/dist/linked-api-tools.js.map +1 -1
  12. package/dist/tools/comment-on-post.d.ts.map +1 -1
  13. package/dist/tools/comment-on-post.js +1 -1
  14. package/dist/tools/comment-on-post.js.map +1 -1
  15. package/dist/tools/create-post.js +1 -1
  16. package/dist/tools/create-post.js.map +1 -1
  17. package/dist/tools/execute-custom-workflow.d.ts.map +1 -1
  18. package/dist/tools/execute-custom-workflow.js +1 -1
  19. package/dist/tools/execute-custom-workflow.js.map +1 -1
  20. package/dist/tools/get-conversation.d.ts +3 -1
  21. package/dist/tools/get-conversation.d.ts.map +1 -1
  22. package/dist/tools/get-conversation.js +20 -3
  23. package/dist/tools/get-conversation.js.map +1 -1
  24. package/dist/tools/get-workflow-result.d.ts +3 -1
  25. package/dist/tools/get-workflow-result.d.ts.map +1 -1
  26. package/dist/tools/get-workflow-result.js +7 -4
  27. package/dist/tools/get-workflow-result.js.map +1 -1
  28. package/dist/tools/nv-get-conversation.d.ts +3 -1
  29. package/dist/tools/nv-get-conversation.d.ts.map +1 -1
  30. package/dist/tools/nv-get-conversation.js +20 -3
  31. package/dist/tools/nv-get-conversation.js.map +1 -1
  32. package/dist/tools/nv-send-message.js +1 -1
  33. package/dist/tools/nv-send-message.js.map +1 -1
  34. package/dist/tools/react-to-post.js +1 -1
  35. package/dist/tools/react-to-post.js.map +1 -1
  36. package/dist/tools/remove-connection.js +1 -1
  37. package/dist/tools/remove-connection.js.map +1 -1
  38. package/dist/tools/send-connection-request.js +1 -1
  39. package/dist/tools/send-connection-request.js.map +1 -1
  40. package/dist/tools/send-message.d.ts.map +1 -1
  41. package/dist/tools/send-message.js +1 -1
  42. package/dist/tools/send-message.js.map +1 -1
  43. package/dist/tools/withdraw-connection-request.js +1 -1
  44. package/dist/tools/withdraw-connection-request.js.map +1 -1
  45. package/dist/utils/define-request-timeout.d.ts.map +1 -1
  46. package/dist/utils/define-request-timeout.js +16 -4
  47. package/dist/utils/define-request-timeout.js.map +1 -1
  48. package/dist/utils/execute-with-progress.d.ts +7 -2
  49. package/dist/utils/execute-with-progress.d.ts.map +1 -1
  50. package/dist/utils/execute-with-progress.js +19 -9
  51. package/dist/utils/execute-with-progress.js.map +1 -1
  52. package/dist/utils/handle-linked-api-error.d.ts +1 -1
  53. package/dist/utils/handle-linked-api-error.d.ts.map +1 -1
  54. package/dist/utils/handle-linked-api-error.js +10 -0
  55. package/dist/utils/handle-linked-api-error.js.map +1 -1
  56. package/dist/utils/json-http-transport.d.ts.map +1 -1
  57. package/dist/utils/json-http-transport.js +4 -3
  58. package/dist/utils/json-http-transport.js.map +1 -1
  59. package/dist/utils/linked-api-tool.d.ts +10 -14
  60. package/dist/utils/linked-api-tool.d.ts.map +1 -1
  61. package/dist/utils/linked-api-tool.js +5 -6
  62. package/dist/utils/linked-api-tool.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/index.ts +46 -9
  65. package/src/linked-api-server.ts +64 -16
  66. package/src/linked-api-tools.ts +52 -31
  67. package/src/tools/comment-on-post.ts +2 -1
  68. package/src/tools/create-post.ts +1 -1
  69. package/src/tools/execute-custom-workflow.ts +2 -1
  70. package/src/tools/get-conversation.ts +27 -3
  71. package/src/tools/get-workflow-result.ts +10 -3
  72. package/src/tools/nv-get-conversation.ts +27 -3
  73. package/src/tools/nv-send-message.ts +1 -1
  74. package/src/tools/react-to-post.ts +1 -1
  75. package/src/tools/remove-connection.ts +1 -1
  76. package/src/tools/send-connection-request.ts +1 -1
  77. package/src/tools/send-message.ts +2 -1
  78. package/src/tools/withdraw-connection-request.ts +1 -1
  79. package/src/utils/define-request-timeout.ts +16 -4
  80. package/src/utils/execute-with-progress.ts +37 -19
  81. package/src/utils/handle-linked-api-error.ts +12 -1
  82. package/src/utils/json-http-transport.ts +4 -3
  83. package/src/utils/linked-api-tool.ts +16 -18
@@ -2,23 +2,33 @@ import { LinkedApiWorkflowTimeoutError, Operation, TMappedResponse } from '@link
2
2
 
3
3
  import { LinkedApiProgressNotification } from './types';
4
4
 
5
- export async function executeWithProgress<TParams, TResult>(
6
- progressCallback: (progress: LinkedApiProgressNotification) => void,
7
- operation: Operation<TParams, TResult>,
8
- workflowTimeout: number,
9
- {
10
- params,
11
- workflowId,
12
- progressToken,
13
- }: { params?: TParams; workflowId?: string; progressToken?: string | number } = {},
14
- ): Promise<TMappedResponse<TResult>> {
5
+ const WORKFLOW_PROGRESS_TOTAL = 100 as const;
6
+ const MIN_PROGRESS_INTERVAL = 10000 as const;
7
+
8
+ interface TExecuteWithProgressOptions<TParams, TResult> {
9
+ progressCallback: (progress: LinkedApiProgressNotification) => void;
10
+ operation: Operation<TParams, TResult>;
11
+ workflowTimeout: number;
12
+ params?: TParams;
13
+ workflowId?: string;
14
+ progressToken?: string | number;
15
+ }
16
+
17
+ export async function executeWithProgress<TParams, TResult>({
18
+ progressCallback,
19
+ operation,
20
+ workflowTimeout,
21
+ params,
22
+ workflowId,
23
+ progressToken,
24
+ }: TExecuteWithProgressOptions<TParams, TResult>): Promise<TMappedResponse<TResult>> {
15
25
  let progress = 0;
16
26
 
17
27
  progressCallback({
18
28
  progressToken,
19
29
  progress,
20
- total: 100,
21
- message: `Starting workflow ${operation.operationName}...`,
30
+ total: WORKFLOW_PROGRESS_TOTAL,
31
+ message: `Starting Linked API workflow ${operation.operationName}. The action may enter the cloud-browser queue and take several minutes.`,
22
32
  });
23
33
 
24
34
  const interval = setInterval(
@@ -32,16 +42,22 @@ export async function executeWithProgress<TParams, TResult>(
32
42
  progressCallback({
33
43
  progressToken,
34
44
  progress,
35
- total: 100,
36
- message: `Executing workflow ${operation.operationName}...`,
45
+ total: WORKFLOW_PROGRESS_TOTAL,
46
+ message: `Waiting for workflow ${operation.operationName}. Linked API is still processing it in the background.`,
37
47
  });
38
48
  },
39
- Math.max(workflowTimeout / 20, 10000),
49
+ Math.max(workflowTimeout / 20, MIN_PROGRESS_INTERVAL),
40
50
  );
41
51
 
42
52
  try {
43
53
  if (!workflowId) {
44
54
  workflowId = await operation.execute(params as TParams);
55
+ progressCallback({
56
+ progressToken,
57
+ progress,
58
+ total: WORKFLOW_PROGRESS_TOTAL,
59
+ message: `Workflow ${operation.operationName} is queued or running in the background. workflowId: ${workflowId}.`,
60
+ });
45
61
  }
46
62
  const result = await operation.result(workflowId, {
47
63
  timeout: workflowTimeout,
@@ -50,8 +66,8 @@ export async function executeWithProgress<TParams, TResult>(
50
66
 
51
67
  progressCallback({
52
68
  progressToken,
53
- progress: 100,
54
- total: 100,
69
+ progress: WORKFLOW_PROGRESS_TOTAL,
70
+ total: WORKFLOW_PROGRESS_TOTAL,
55
71
  message: `Workflow ${operation.operationName} completed successfully`,
56
72
  });
57
73
 
@@ -66,8 +82,10 @@ export async function executeWithProgress<TParams, TResult>(
66
82
  }
67
83
  }
68
84
 
69
- function generateTimeoutError(error: LinkedApiWorkflowTimeoutError) {
70
- const restoreMessage = `Workflow is running in the background. Continue listening for updates.
85
+ function generateTimeoutError(error: LinkedApiWorkflowTimeoutError): LinkedApiWorkflowTimeoutError {
86
+ const restoreMessage = `Workflow is still running in Linked API's cloud-browser queue or background worker.
87
+
88
+ This is not a failure. The original tool already started the workflow, so retrying it can create duplicate queued work.
71
89
 
72
90
  ACTION REQUIRED (MCP CLIENT):
73
91
  - Do not retry the original tool; the workflow is already running
@@ -2,13 +2,24 @@ import { LinkedApiError, LinkedApiWorkflowTimeoutError } from '@linkedapi/node';
2
2
 
3
3
  import { authenticationPrompt } from '../prompts';
4
4
 
5
- export function handleLinkedApiError(error: LinkedApiError): object {
5
+ export function handleLinkedApiError(error: LinkedApiError): Record<string, unknown> {
6
6
  if (error instanceof LinkedApiWorkflowTimeoutError) {
7
7
  const { message, workflowId, operationName } = error;
8
8
  return {
9
+ status: 'workflow_running',
9
10
  message,
10
11
  workflowId,
11
12
  operationName,
13
+ nextAction: {
14
+ tool: 'get_workflow_result',
15
+ arguments: {
16
+ workflowId,
17
+ operationName,
18
+ },
19
+ repeatUntil: 'final data is returned or the tool returns Completed',
20
+ },
21
+ userMessage:
22
+ 'Linked API is still working through the cloud-browser workflow. I will keep checking the existing workflow instead of starting a duplicate request.',
12
23
  };
13
24
  }
14
25
  switch (error.type) {
@@ -77,12 +77,13 @@ export class JsonHTTPServerTransport implements Transport {
77
77
  }
78
78
 
79
79
  async send(message: JSONRPCMessage, options?: TransportSendOptions): Promise<void> {
80
+ const isResponse = isJSONRPCResponse(message) || isJSONRPCError(message);
80
81
  let relatedId = options?.relatedRequestId;
81
- if (isJSONRPCResponse(message) || isJSONRPCError(message)) {
82
+ if (isResponse) {
82
83
  relatedId = message.id;
83
84
  }
84
- // If a related HTTP connection is pending, complete it with JSON
85
- if (relatedId !== undefined) {
85
+ // If a related HTTP connection is pending, only final responses complete it.
86
+ if (isResponse && relatedId !== undefined) {
86
87
  const connId = this.requestIdToConn.get(relatedId);
87
88
  if (connId) {
88
89
  const ctx = this.connections.get(connId);
@@ -5,14 +5,17 @@ import z from 'zod';
5
5
 
6
6
  import { executeWithProgress } from './execute-with-progress';
7
7
 
8
+ interface TLinkedApiToolExecuteOptions<TParams> {
9
+ linkedapi: LinkedApi;
10
+ args: TParams;
11
+ workflowTimeout: number;
12
+ progressToken?: string | number;
13
+ progressCallback: (progress: LinkedApiProgressNotification) => void;
14
+ }
15
+
8
16
  export abstract class LinkedApiTool<TParams, TResult> {
9
17
  public abstract readonly name: string;
10
18
  protected abstract readonly schema: z.ZodSchema;
11
- protected readonly progressCallback: (progress: LinkedApiProgressNotification) => void;
12
-
13
- constructor(progressCallback: (progress: LinkedApiProgressNotification) => void) {
14
- this.progressCallback = progressCallback;
15
- }
16
19
 
17
20
  public abstract getTool(): Tool;
18
21
 
@@ -25,12 +28,8 @@ export abstract class LinkedApiTool<TParams, TResult> {
25
28
  args,
26
29
  workflowTimeout,
27
30
  progressToken,
28
- }: {
29
- linkedapi: LinkedApi;
30
- args: TParams;
31
- workflowTimeout: number;
32
- progressToken?: string | number;
33
- }): Promise<TMappedResponse<TResult>>;
31
+ progressCallback,
32
+ }: TLinkedApiToolExecuteOptions<TParams>): Promise<TMappedResponse<TResult>>;
34
33
  }
35
34
 
36
35
  export abstract class OperationTool<TParams, TResult> extends LinkedApiTool<TParams, TResult> {
@@ -41,16 +40,15 @@ export abstract class OperationTool<TParams, TResult> extends LinkedApiTool<TPar
41
40
  args,
42
41
  workflowTimeout,
43
42
  progressToken,
44
- }: {
45
- linkedapi: LinkedApi;
46
- args: TParams;
47
- workflowTimeout: number;
48
- progressToken?: string | number;
49
- }): Promise<TMappedResponse<TResult>> {
43
+ progressCallback,
44
+ }: TLinkedApiToolExecuteOptions<TParams>): Promise<TMappedResponse<TResult>> {
50
45
  const operation = linkedapi.operations.find(
51
46
  (operation) => operation.operationName === this.operationName,
52
47
  )! as Operation<TParams, TResult>;
53
- return executeWithProgress(this.progressCallback, operation, workflowTimeout, {
48
+ return executeWithProgress({
49
+ progressCallback,
50
+ operation,
51
+ workflowTimeout,
54
52
  params: args,
55
53
  progressToken,
56
54
  });