Initial commit

This commit is contained in:
odiinnn committed 2025-05-24 12:31:14 +03:00
commit 56fb2646df
31 files changed
+3961

No files matched your search

+1
View File
@@ -0,0 +1 @@
.git
+10
View File
@@ -0,0 +1,10 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
[*.{js,json,yml}]
charset = utf-8
indent_style = space
indent_size = 2
+14
View File
@@ -0,0 +1,14 @@
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
node_modules
.env
build/*
*.tgz
.qodo
+49
View File
@@ -0,0 +1,49 @@
stages:
- build
- deploy
variables:
VERSION: 0.8.${CI_PIPELINE_ID}
SERVER_USER: $SERVER_USER
CI_REGISTRY: repo.mind-dev.com
CONTAINER_IMAGE: $CI_REGISTRY/mind-dev/santiment-mcp/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA
CONTAINER_RELEASE_IMAGE: $CI_REGISTRY/mind-dev/santiment-mcp/$CI_COMMIT_REF_NAME:latest
build:
image: docker:19-dind
services:
- docker:19-dind
stage: build
tags:
- jenkins-build
variables:
DOCKER_DRIVER: overlay2
only:
- main
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- cat $ENV_FILE > .env
- docker pull $CONTAINER_RELEASE_IMAGE || true
- docker build --cache-from $CONTAINER_RELEASE_IMAGE --tag $CONTAINER_IMAGE --tag $CONTAINER_RELEASE_IMAGE . -f Dockerfile
- docker push $CONTAINER_IMAGE
- docker push $CONTAINER_RELEASE_IMAGE
.deploy:
stage: deploy
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker pull $CONTAINER_RELEASE_IMAGE
- cd $path
- docker-compose up -d frontend
deploy:
extends: .deploy
tags:
- gitlab-runner
only:
- main
variables:
path: /var/www/santiment-mcp
+24
View File
@@ -0,0 +1,24 @@
# Source files (since we're publishing the compiled output)
src/
# Development files
.editorconfig
.gitignore
.yarnrc.yml
tsconfig.json
yarn.lock
node_modules/
# Environment and configuration files
.env
.env.*
claude_desktop_config.json
# Test files
test-mcp.js
# Misc
.DS_Store
.vscode/
.idea/
*.log
+1
View File
@@ -0,0 +1 @@
engine-strict=true
+8
View File
@@ -0,0 +1,8 @@
{
"plugins": ["@ianvs/prettier-plugin-sort-imports"],
"importOrder": ["<THIRD_PARTY_MODULES>", "^@/(.*)$", "^[./]"],
"importOrderParserPlugins": ["typescript", "jsx", "decorators-legacy"],
"semi": true,
"singleQuote": true,
"trailingComma": "all"
}
+5
View File
@@ -0,0 +1,5 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
+1
View File
@@ -0,0 +1 @@
nodeLinker: node-modules
+28
View File
@@ -0,0 +1,28 @@
# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile
FROM node:23.10.0-alpine3.21
# Create app directory
WORKDIR /usr/src/app
# Copy package files and config first
COPY package.json yarn.lock tsconfig.json ./
# Copy source code
COPY src/ ./src/
COPY .env ./
COPY patches/ ./patches/
# Install dependencies including TypeScript
RUN yarn install --frozen-lockfile
# Build the project (using local tsc from node_modules)
RUN yarn build
# Expose port for the SSE server
EXPOSE 3000
# Set environment variables
ENV SSE_PORT=3000
# Run the server using the correct build path
CMD ["node", "build/index.js"]
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Liquidswap MCP Server Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+7
View File
@@ -0,0 +1,7 @@
Liquidswap MCP server
```
yarn build
yarn start
```
+35
View File
@@ -0,0 +1,35 @@
import pluginJs from '@eslint/js';
import globals from 'globals';
import tseslint from 'typescript-eslint';
/** @type {import('eslint').Linter.Config[]} */
export default [
{ files: ['**/*.{js,mjs,cjs,ts}'] },
{ languageOptions: { globals: globals.node } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
{
ignores: [
'**/node_modules/**',
'**/build/**',
'scripts/**',
'.yarn/**',
'**/*.json',
'**/*.md',
],
},
{
rules: {
// Disallow console.log but allow console.error, console.warn, and console.info
'no-console': ['error', { allow: ['error', 'warn', 'info'] }],
// TypeScript specific rules
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_' },
],
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
},
];
+13
View File
@@ -0,0 +1,13 @@
{
"mcpServers": {
"liquidswap-mcp": {
"command": "node",
"args": ["PATH_TO_INDEX_JS"],
"env": {
"SSE_PORT": "3000"
},
"disabled": false,
"autoApprove": []
}
}
}
+66
View File
@@ -0,0 +1,66 @@
{
"name": "liquidswap-mcp",
"version": "1.0.0",
"description": "A Model Context Protocol (MCP) server that provides for Liquidswap",
"bin": "./build/index.js",
"type": "module",
"scripts": {
"postinstall": "patch-package",
"build": "npx rimraf build && tsc -p tsconfig.json && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
"start": "node build/index.js",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint src/**/*.ts --fix",
"format": "prettier --write .",
"prepare": "npm run build",
"publish": "rm -rf dist && rm -rf node_modules && npm i && npm run build && npm publish"
},
"files": [
"build"
],
"repository": {
"type": "git",
"url": ""
},
"keywords": [
"mcp",
"liquidswap",
"aptos",
"ai"
],
"author": "odiinnn",
"license": "MIT",
"packageManager": "yarn@1.22.21",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.6.1",
"dotenv": "^16.4.7",
"express": "^4.21.2",
"fastmcp": "^1.21.0",
"graphql": "^16.10.0",
"graphql-request": "^7.1.2",
"node-fetch": "^3.3.2",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"reflect-metadata": "^0.2.2",
"zod": "^3.24.2"
},
"devDependencies": {
"@eslint/js": "^9.22.0",
"@ianvs/prettier-plugin-sort-imports": "^4.4.1",
"@types/express": "^5.0.1",
"@types/node": "^22.13.9",
"@types/react": "^19",
"@types/react-dom": "^19",
"@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1",
"eslint": "^9.22.0",
"eslint-config-prettier": "^10.1.1",
"eslint-plugin-import": "^2.31.0",
"globals": "^16.0.0",
"nodemon": "^3.1.9",
"prettier": "^3.5.3",
"ts-node": "^10.9.2",
"typescript": "^5.8.2",
"typescript-eslint": "^8.26.1",
"zod-to-json-schema": "^3.24.4"
}
}
BIN
View File
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
import { config } from "dotenv";
config();
export const BE_URL = process.env.BE_URL || 'https://api.liquidswap.com';
+22
View File
@@ -0,0 +1,22 @@
import { BE_URL } from "../constants.js";
export class Liquidswap {
private readonly url = BE_URL
private async fetch(url: string) {
const response = await fetch(`${this.url}${url}`)
return response.json()
}
public async getTokens() {
const response = await this.fetch(`/coins/registered`)
return response
}
public async getPools() {
const response = await this.fetch(`/pools/registered?networkId=1&cl=true`)
return response
}
}
export const liquidswap = new Liquidswap()
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env node
import { config } from "dotenv";
config();
import { setupServer } from "./transports/setup-server.js";
const SSE_PORT = process.env.SSE_PORT || 3001;
// Start the server
async function main() {
await setupServer().then((app) => {
app.start({
transportType: "sse",
sse: {
endpoint: "/sse",
port: Number(SSE_PORT),
},
});
});
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
+4
View File
@@ -0,0 +1,4 @@
import { Resource } from "../types/resources.js";
export const resourses: Resource[] = []
+23
View File
@@ -0,0 +1,23 @@
import type { Tool } from "../../types/tools.js";
import { liquidswap } from "../../core/liquidswap.js";
import { z } from "zod";
const getPools: Tool<typeof parameters>['execute'] = async () => {
const data = await liquidswap.getPools();
return {
type: "text",
text: JSON.stringify(data, null, 2),
};
};
const parameters = z.object({});
export const getPoolsTool: Tool<typeof parameters> = {
name: "get_pools",
description: "Get all pools registered on Liquidswap",
execute: getPools,
parameters,
};
+1
View File
@@ -0,0 +1 @@
export * from "./get-pools.js";
+23
View File
@@ -0,0 +1,23 @@
import type { Tool } from "../../types/tools.js";
import { liquidswap } from "../../core/liquidswap.js";
import { z } from "zod";
const getTokens: Tool<typeof parameters>['execute'] = async () => {
const data = await liquidswap.getTokens();
return {
type: "text",
text: JSON.stringify(data, null, 2),
};
};
const parameters = z.object({});
export const getTokensTool: Tool<typeof parameters> = {
name: "get_tokens",
description: "Get all tokens registered on Liquidswap",
execute: getTokens,
parameters,
};
+1
View File
@@ -0,0 +1 @@
export * from "./get-tokens.js";
+10
View File
@@ -0,0 +1,10 @@
import { Tool } from "../types/tools.js";
import { getTokensTool } from "./get-tokens/get-tokens.js";
import { getPoolsTool } from "./get-pools/get-pools.js";
const tools: Tool<any>[] = [
getTokensTool,
getPoolsTool,
];
export default tools;
+72
View File
@@ -0,0 +1,72 @@
import { resourses } from "../resources/all-resources.js";
import { FastMCP } from "fastmcp";
import * as fastmcp from "fastmcp";
import { name, version } from "../version.js";
import tools from "../tools/index.js";
import { liquidswap } from "../core/liquidswap.js";
function setupServerHandlers(server: FastMCP) {
for (const resource of resourses) {
if ('arguments' in resource && resource.arguments) {
server.addResourceTemplate({
uriTemplate: `liquidswap://${resource.pathname}`,
name: resource.name,
mimeType: resource.mimeType,
arguments: resource.arguments,
load: async (args) => {
return resource.handler(liquidswap, args);
},
});
}
server.addResource({
uri: `liquidswap://${resource.pathname}`,
name: resource.name,
mimeType: resource.mimeType,
async load() {
return resource.handler(liquidswap, {});
},
});
}
for (const tool of tools) {
server.addTool(tool);
}
}
class FastMCPSession extends fastmcp.FastMCPSession {
originalEmit = fastmcp.FastMCPSession.prototype.emit;
}
Object.defineProperty(fastmcp.FastMCPSession.prototype, "originalEmit", {
value: fastmcp.FastMCPSession.prototype.emit,
writable: false,
});
// suppress error event
fastmcp.FastMCPSession.prototype.emit = function (
this: FastMCPSession,
event: any,
...args: any[]
) {
if (event !== "error") {
return this.originalEmit(event, ...args);
}
};
export async function setupServer() {
const server = new FastMCP(
{
name,
version
},
);
setupServerHandlers(server);
return server;
}
export default setupServer;
+23
View File
@@ -0,0 +1,23 @@
import { Liquidswap } from "../core/liquidswap.js";
import type { ResourceResult, ResourceTemplateArgument } from "fastmcp";
type ResourceTemplateArgumentsToObject<T extends {
name: string;
}[]> = {
[K in T[number]["name"]]: string;
};
export type ResourceHandler<Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[]> = (santiment: Liquidswap, args: ResourceTemplateArgumentsToObject<Arguments>) => Promise<Arguments extends (ResourceResult | ResourceResult[]) ? (ResourceResult | ResourceResult[]) : ResourceResult>;
export type Resource<Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[]> = {
pathname: string;
name: string;
description: string;
mimeType: `text/${string}` | `application/${string}`;
handler: ResourceHandler<Arguments>;
arguments?: Arguments;
} | {
pathname: string;
name: string;
description: string;
mimeType: `text/${string}` | `application/${string}`;
handler: ResourceHandler;
}
+3
View File
@@ -0,0 +1,3 @@
import type { Tool as fastmcpTool, ToolParameters } from "fastmcp";
export type Tool<Parameters extends ToolParameters = ToolParameters> = fastmcpTool<undefined, Parameters>;
+2
View File
@@ -0,0 +1,2 @@
export const version = "1.0.0";
export const name = "liquidswap-mcp-server";
+18
View File
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
+3445
View File
File diff suppressed because it is too large. Load diff