Skip to content

Commit

Permalink
feat: mcp server
Browse files Browse the repository at this point in the history
  • Loading branch information
utkarsh-dixit committed Feb 28, 2025
1 parent ee70499 commit 5543edc
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 18 deletions.
Empty file added js/[email protected]
Empty file.
Empty file added js/jest
Empty file.
1 change: 1 addition & 0 deletions js/src/sdk/base.toolset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ export class ComposioToolSet {
params = await processor({
params: params,
actionName: action,
client: this.client.backendClient.instance,
});
}

Expand Down
35 changes: 23 additions & 12 deletions js/src/sdk/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,15 @@ describe("Basic SDK spec suite", () => {
name: "AppNotFoundError",
message: "Not found",
};
mock.onGet(/.*\/api\/v1\/apps/).reply(404, mockError);

const client = new Composio({
apiKey: COMPOSIO_API_KEY,
baseUrl: getTestConfig().BACKEND_HERMES_URL,
});

const mock = new AxiosMockAdapter(client.backendClient.getAxiosInstance());

mock.onGet(/.*\/api\/v1\/apps/).reply(404, mockError);
let errorWasThrown = false;
try {
await client.apps.list();
Expand All @@ -98,9 +100,19 @@ describe("Basic SDK spec suite", () => {
}
}
expect(errorWasThrown).toBe(true);
mock.reset();
});

it("should handle 400 error gracefully", async () => {


let errorWasThrown = false;
const client = new Composio({
apiKey: COMPOSIO_API_KEY,
baseUrl: getTestConfig().BACKEND_HERMES_URL,
});

const mock = new AxiosMockAdapter(client.backendClient.getAxiosInstance());
mock.onGet(/.*\/api\/v1\/apps/).reply(400, {
type: "BadRequestError",
name: "InvalidRequestError",
Expand All @@ -115,12 +127,6 @@ describe("Basic SDK spec suite", () => {
},
],
});

let errorWasThrown = false;
const client = new Composio({
apiKey: COMPOSIO_API_KEY,
baseUrl: getTestConfig().BACKEND_HERMES_URL,
});
try {
await client.apps.list();
} catch (e) {
Expand All @@ -134,19 +140,21 @@ describe("Basic SDK spec suite", () => {
);
}
expect(errorWasThrown).toBe(true);
mock.reset();
});

it("should handle 500 and 502 error gracefully, and without backend fix", async () => {
mock.onGet(/.*\/api\/v1\/apps/).reply(500, {
type: "InternalServerError",
name: "ServerError",
message: "Internal Server Error",
});
let errorWasThrown = false;
const client = new Composio({
apiKey: COMPOSIO_API_KEY,
baseUrl: getTestConfig().BACKEND_HERMES_URL,
});
const mock = new AxiosMockAdapter(client.backendClient.getAxiosInstance());
mock.onGet(/.*\/api\/v1\/apps/).reply(500, {
type: "InternalServerError",
name: "ServerError",
message: "Internal Server Error",
});
try {
await client.apps.list();
} catch (e) {
Expand Down Expand Up @@ -195,13 +203,15 @@ describe("Basic SDK spec suite", () => {
const error = e as ComposioError;
expect(error.errCode).toBe(COMPOSIO_SDK_ERROR_CODES.BACKEND.SERVER_ERROR);
}
mock.reset();
});

it("should give request timeout error", async () => {
const client = new Composio({
apiKey: COMPOSIO_API_KEY,
baseUrl: getTestConfig().BACKEND_HERMES_URL,
});
const mock = new AxiosMockAdapter(client.backendClient.getAxiosInstance());

mock.onGet(/.*\/api\/v1\/apps/).reply(408, {
error: {
Expand All @@ -225,6 +235,7 @@ describe("Basic SDK spec suite", () => {
}

expect(errorWasThrown).toBe(true);
mock.reset()
});

it("syntax error handling", async () => {
Expand Down
10 changes: 7 additions & 3 deletions js/src/sdk/utils/processor/file.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Client } from "@hey-api/client-axios";
import {
TPostProcessor,
TPreProcessor,
Expand Down Expand Up @@ -31,7 +32,8 @@ const convertFileSchemaProperty = (

const processFileUpload = async (
params: Record<string, unknown>,
actionName: string
actionName: string,
client: Client
) => {
const result = { ...params };

Expand All @@ -41,7 +43,8 @@ const processFileUpload = async (
const originalKey = key.replace(FILE_SUFFIX, "");
const fileData = await getFileDataAfterUploadingToS3(
value as string,
actionName
actionName,
client
);

result[originalKey] = fileData;
Expand All @@ -54,8 +57,9 @@ const processFileUpload = async (
export const FILE_INPUT_PROCESSOR: TPreProcessor = async ({
params,
actionName,
client
}) => {
return processFileUpload(params, actionName);
return processFileUpload(params, actionName, client);
};

export const FILE_DOWNLOADABLE_PROCESSOR: TPostProcessor = async ({
Expand Down
11 changes: 8 additions & 3 deletions js/src/sdk/utils/processor/fileUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import axios, { AxiosError } from "axios";
import crypto from "crypto";
import apiClient from "../../client/client";
import { saveFile } from "../fileUtils";
import { Client } from "@hey-api/client-axios";

const readFileContent = async (
path: string
Expand Down Expand Up @@ -36,10 +37,12 @@ const uploadFileToS3 = async (
content: string,
actionName: string,
appName: string,
mimeType: string
mimeType: string,
client: Client
): Promise<string> => {
const extension = mimeType.split("/")[1] || "bin";
const response = await apiClient.actionsV2.createFileUploadUrl({
client: client,
body: {
action: actionName,
app: appName,
Expand Down Expand Up @@ -80,7 +83,8 @@ const uploadFileToS3 = async (

export const getFileDataAfterUploadingToS3 = async (
path: string,
actionName: string
actionName: string,
client: Client
): Promise<{
name: string;
mimetype: string;
Expand All @@ -95,7 +99,8 @@ export const getFileDataAfterUploadingToS3 = async (
fileData.content,
actionName,
actionName,
fileData.mimeType
fileData.mimeType,
client
);

return {
Expand Down
2 changes: 2 additions & 0 deletions js/src/types/base_toolset.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z } from "zod";
import { ActionExecutionResDto } from "../sdk/client";
import { Client } from "@hey-api/client-axios";

/*
This is the schema for the raw action to be stored locally
Expand Down Expand Up @@ -52,6 +53,7 @@ export type TPreProcessor = ({
}: {
params: Record<string, unknown>;
actionName: string;
client: Client;
}) => Promise<Record<string, unknown>> | Record<string, unknown>;

export type TPostProcessor = ({
Expand Down

0 comments on commit 5543edc

Please sign in to comment.