Squashed 'packages/mcp-typescript/' changes from e665be0..7d70db8
7d70db8 Merge pull request #20 from modelcontextprotocol/ashwin/progress 65a8613 fix schema definitions for RequestSchema git-subtree-dir: packages/mcp-typescript git-subtree-split: 7d70db805740c53f21153d72be6f34d70818a9da
This commit is contained in:
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,2 +1 @@
|
|||||||
yarn.lock linguist-generated=true
|
dist/**/* linguist-generated=true
|
||||||
packages/**/* linguist-generated=true
|
|
||||||
|
|||||||
134
.gitignore
vendored
134
.gitignore
vendored
@@ -1,5 +1,131 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
.temp
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
|
||||||
server/build
|
|
||||||
client/dist
|
|
||||||
client/tsconfig.app.tsbuildinfo
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
packages
|
|
||||||
server/build
|
|
||||||
26
README.md
26
README.md
@@ -1,24 +1,2 @@
|
|||||||
# MCP Inspector
|
# mcp-typescript
|
||||||
|
TypeScript implementation of the Model Context Protocol
|
||||||
The MCP inspector is a developer tool for testing and debugging MCP servers.
|
|
||||||
|
|
||||||
Setup:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn
|
|
||||||
```
|
|
||||||
|
|
||||||
You can run it in dev mode via:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn dev
|
|
||||||
```
|
|
||||||
|
|
||||||
This will start both the client and server.
|
|
||||||
|
|
||||||
To run in production mode:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn build
|
|
||||||
yarn start
|
|
||||||
```
|
|
||||||
|
|||||||
24
client/.gitignore
vendored
24
client/.gitignore
vendored
@@ -1,24 +0,0 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
*.local
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
.DS_Store
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
# React + TypeScript + Vite
|
|
||||||
|
|
||||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
||||||
|
|
||||||
Currently, two official plugins are available:
|
|
||||||
|
|
||||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
|
||||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
|
||||||
|
|
||||||
## Expanding the ESLint configuration
|
|
||||||
|
|
||||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
|
||||||
|
|
||||||
- Configure the top-level `parserOptions` property like this:
|
|
||||||
|
|
||||||
```js
|
|
||||||
export default tseslint.config({
|
|
||||||
languageOptions: {
|
|
||||||
// other options...
|
|
||||||
parserOptions: {
|
|
||||||
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
|
|
||||||
tsconfigRootDir: import.meta.dirname,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
|
|
||||||
- Optionally add `...tseslint.configs.stylisticTypeChecked`
|
|
||||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
|
|
||||||
|
|
||||||
```js
|
|
||||||
// eslint.config.js
|
|
||||||
import react from "eslint-plugin-react";
|
|
||||||
|
|
||||||
export default tseslint.config({
|
|
||||||
// Set the react version
|
|
||||||
settings: { react: { version: "18.3" } },
|
|
||||||
plugins: {
|
|
||||||
// Add the react plugin
|
|
||||||
react,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
// other rules...
|
|
||||||
// Enable its recommended rules
|
|
||||||
...react.configs.recommended.rules,
|
|
||||||
...react.configs["jsx-runtime"].rules,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://ui.shadcn.com/schema.json",
|
|
||||||
"style": "new-york",
|
|
||||||
"rsc": false,
|
|
||||||
"tsx": true,
|
|
||||||
"tailwind": {
|
|
||||||
"config": "tailwind.config.js",
|
|
||||||
"css": "src/index.css",
|
|
||||||
"baseColor": "slate",
|
|
||||||
"cssVariables": true,
|
|
||||||
"prefix": ""
|
|
||||||
},
|
|
||||||
"aliases": {
|
|
||||||
"components": "@/components",
|
|
||||||
"utils": "@/lib/utils",
|
|
||||||
"ui": "@/components/ui",
|
|
||||||
"lib": "@/lib",
|
|
||||||
"hooks": "@/hooks"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import js from "@eslint/js";
|
|
||||||
import globals from "globals";
|
|
||||||
import reactHooks from "eslint-plugin-react-hooks";
|
|
||||||
import reactRefresh from "eslint-plugin-react-refresh";
|
|
||||||
import tseslint from "typescript-eslint";
|
|
||||||
|
|
||||||
export default tseslint.config(
|
|
||||||
{ ignores: ["dist"] },
|
|
||||||
{
|
|
||||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
||||||
files: ["**/*.{ts,tsx}"],
|
|
||||||
languageOptions: {
|
|
||||||
ecmaVersion: 2020,
|
|
||||||
globals: globals.browser,
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
"react-hooks": reactHooks,
|
|
||||||
"react-refresh": reactRefresh,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
...reactHooks.configs.recommended.rules,
|
|
||||||
"react-refresh/only-export-components": [
|
|
||||||
"warn",
|
|
||||||
{ allowConstantExport: true },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Vite + React + TS</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "client",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "tsc -b && vite build",
|
|
||||||
"lint": "eslint .",
|
|
||||||
"preview": "vite preview"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
|
||||||
"@radix-ui/react-label": "^2.1.0",
|
|
||||||
"@radix-ui/react-select": "^2.1.2",
|
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
|
||||||
"@radix-ui/react-tabs": "^1.1.1",
|
|
||||||
"class-variance-authority": "^0.7.0",
|
|
||||||
"clsx": "^2.1.1",
|
|
||||||
"lucide-react": "^0.447.0",
|
|
||||||
"mcp-typescript": "file:../packages/mcp-typescript",
|
|
||||||
"react": "^18.3.1",
|
|
||||||
"react-dom": "^18.3.1",
|
|
||||||
"tailwind-merge": "^2.5.3",
|
|
||||||
"tailwindcss-animate": "^1.0.7"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@eslint/js": "^9.11.1",
|
|
||||||
"@types/node": "^22.7.5",
|
|
||||||
"@types/react": "^18.3.10",
|
|
||||||
"@types/react-dom": "^18.3.0",
|
|
||||||
"@vitejs/plugin-react": "^4.3.2",
|
|
||||||
"autoprefixer": "^10.4.20",
|
|
||||||
"eslint": "^9.11.1",
|
|
||||||
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
|
||||||
"eslint-plugin-react-refresh": "^0.4.12",
|
|
||||||
"globals": "^15.9.0",
|
|
||||||
"postcss": "^8.4.47",
|
|
||||||
"tailwindcss": "^3.4.13",
|
|
||||||
"typescript": "^5.5.3",
|
|
||||||
"typescript-eslint": "^8.7.0",
|
|
||||||
"vite": "^5.4.8"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
export default {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,42 +0,0 @@
|
|||||||
#root {
|
|
||||||
max-width: 1280px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
height: 6em;
|
|
||||||
padding: 1.5em;
|
|
||||||
will-change: filter;
|
|
||||||
transition: filter 300ms;
|
|
||||||
}
|
|
||||||
.logo:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #646cffaa);
|
|
||||||
}
|
|
||||||
.logo.react:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes logo-spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
a:nth-of-type(2) .logo {
|
|
||||||
animation: logo-spin infinite 20s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
padding: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.read-the-docs {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
@@ -1,323 +0,0 @@
|
|||||||
import { Client } from "mcp-typescript/client/index.js";
|
|
||||||
import { SSEClientTransport } from "mcp-typescript/client/sse.js";
|
|
||||||
import {
|
|
||||||
ListResourcesResultSchema,
|
|
||||||
GetPromptResultSchema,
|
|
||||||
ListToolsResultSchema,
|
|
||||||
ReadResourceResultSchema,
|
|
||||||
CallToolResultSchema,
|
|
||||||
ListPromptsResultSchema,
|
|
||||||
Tool,
|
|
||||||
ClientRequest,
|
|
||||||
} from "mcp-typescript/types.js";
|
|
||||||
import { useState } from "react";
|
|
||||||
import {
|
|
||||||
Send,
|
|
||||||
Bell,
|
|
||||||
Terminal,
|
|
||||||
Files,
|
|
||||||
MessageSquare,
|
|
||||||
Hammer,
|
|
||||||
Play,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/components/ui/select";
|
|
||||||
|
|
||||||
import ConsoleTab from "./components/ConsoleTab";
|
|
||||||
import Sidebar from "./components/Sidebar";
|
|
||||||
import RequestsTab from "./components/RequestsTabs";
|
|
||||||
import ResourcesTab, { Resource } from "./components/ResourcesTab";
|
|
||||||
import NotificationsTab from "./components/NotificationsTab";
|
|
||||||
import PromptsTab, { Prompt } from "./components/PromptsTab";
|
|
||||||
import ToolsTab from "./components/ToolsTab";
|
|
||||||
import History from "./components/History";
|
|
||||||
import { AnyZodObject } from "node_modules/zod/lib";
|
|
||||||
|
|
||||||
const App = () => {
|
|
||||||
const [connectionStatus, setConnectionStatus] = useState<
|
|
||||||
"disconnected" | "connected" | "error"
|
|
||||||
>("disconnected");
|
|
||||||
const [resources, setResources] = useState<Resource[]>([]);
|
|
||||||
const [resourceContent, setResourceContent] = useState<string>("");
|
|
||||||
const [prompts, setPrompts] = useState<Prompt[]>([]);
|
|
||||||
const [promptContent, setPromptContent] = useState<string>("");
|
|
||||||
const [tools, setTools] = useState<Tool[]>([]);
|
|
||||||
const [toolResult, setToolResult] = useState<string>("");
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
const [command, setCommand] = useState<string>(
|
|
||||||
"/Users/ashwin/.nvm/versions/node/v18.20.4/bin/node",
|
|
||||||
);
|
|
||||||
const [args, setArgs] = useState<string>(
|
|
||||||
"/Users/ashwin/code/example-servers/build/everything/stdio.js",
|
|
||||||
);
|
|
||||||
const [url, setUrl] = useState<string>("http://localhost:3001/sse");
|
|
||||||
const [transportType, setTransportType] = useState<"stdio" | "sse">("stdio");
|
|
||||||
const [requestHistory, setRequestHistory] = useState<
|
|
||||||
{ request: string; response: string }[]
|
|
||||||
>([]);
|
|
||||||
const [mcpClient, setMcpClient] = useState<Client | null>(null);
|
|
||||||
|
|
||||||
const [selectedResource, setSelectedResource] = useState<Resource | null>(
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
const [selectedPrompt, setSelectedPrompt] = useState<Prompt | null>(null);
|
|
||||||
const [selectedTool, setSelectedTool] = useState<Tool | null>(null);
|
|
||||||
|
|
||||||
const pushHistory = (request: object, response: object) => {
|
|
||||||
setRequestHistory((prev) => [
|
|
||||||
...prev,
|
|
||||||
{ request: JSON.stringify(request), response: JSON.stringify(response) },
|
|
||||||
]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeRequest = async <T extends AnyZodObject>(
|
|
||||||
request: ClientRequest,
|
|
||||||
schema: T,
|
|
||||||
) => {
|
|
||||||
if (!mcpClient) {
|
|
||||||
throw new Error("MCP client not connected");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await mcpClient.request(request, schema);
|
|
||||||
pushHistory(request, response);
|
|
||||||
return response;
|
|
||||||
} catch (e: unknown) {
|
|
||||||
setError((e as Error).message);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const listResources = async () => {
|
|
||||||
const response = await makeRequest(
|
|
||||||
{
|
|
||||||
method: "resources/list" as const,
|
|
||||||
},
|
|
||||||
ListResourcesResultSchema,
|
|
||||||
);
|
|
||||||
if (response.resources) {
|
|
||||||
setResources(response.resources);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const readResource = async (uri: string) => {
|
|
||||||
const response = await makeRequest(
|
|
||||||
{
|
|
||||||
method: "resources/read" as const,
|
|
||||||
params: { uri },
|
|
||||||
},
|
|
||||||
ReadResourceResultSchema,
|
|
||||||
);
|
|
||||||
setResourceContent(JSON.stringify(response, null, 2));
|
|
||||||
};
|
|
||||||
|
|
||||||
const listPrompts = async () => {
|
|
||||||
const response = await makeRequest(
|
|
||||||
{
|
|
||||||
method: "prompts/list" as const,
|
|
||||||
},
|
|
||||||
ListPromptsResultSchema,
|
|
||||||
);
|
|
||||||
setPrompts(response.prompts);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getPrompt = async (name: string, args: Record<string, string> = {}) => {
|
|
||||||
const response = await makeRequest(
|
|
||||||
{
|
|
||||||
method: "prompts/get" as const,
|
|
||||||
params: { name, arguments: args },
|
|
||||||
},
|
|
||||||
GetPromptResultSchema,
|
|
||||||
);
|
|
||||||
setPromptContent(JSON.stringify(response, null, 2));
|
|
||||||
};
|
|
||||||
|
|
||||||
const listTools = async () => {
|
|
||||||
const response = await makeRequest(
|
|
||||||
{
|
|
||||||
method: "tools/list" as const,
|
|
||||||
},
|
|
||||||
ListToolsResultSchema,
|
|
||||||
);
|
|
||||||
setTools(response.tools);
|
|
||||||
};
|
|
||||||
|
|
||||||
const callTool = async (name: string, params: Record<string, unknown>) => {
|
|
||||||
const response = await makeRequest(
|
|
||||||
{
|
|
||||||
method: "tools/call" as const,
|
|
||||||
params: { name, arguments: params },
|
|
||||||
},
|
|
||||||
CallToolResultSchema,
|
|
||||||
);
|
|
||||||
setToolResult(JSON.stringify(response.toolResult, null, 2));
|
|
||||||
};
|
|
||||||
|
|
||||||
const connectMcpServer = async () => {
|
|
||||||
try {
|
|
||||||
const client = new Client({
|
|
||||||
name: "mcp-inspector",
|
|
||||||
version: "0.0.1",
|
|
||||||
});
|
|
||||||
|
|
||||||
const clientTransport = new SSEClientTransport();
|
|
||||||
const backendUrl = new URL("http://localhost:3000/sse");
|
|
||||||
|
|
||||||
backendUrl.searchParams.append("transportType", transportType);
|
|
||||||
if (transportType === "stdio") {
|
|
||||||
backendUrl.searchParams.append("command", command);
|
|
||||||
backendUrl.searchParams.append("args", args);
|
|
||||||
} else {
|
|
||||||
backendUrl.searchParams.append("url", url);
|
|
||||||
}
|
|
||||||
|
|
||||||
await clientTransport.connect(backendUrl);
|
|
||||||
await client.connect(clientTransport);
|
|
||||||
|
|
||||||
setMcpClient(client);
|
|
||||||
setConnectionStatus("connected");
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
setConnectionStatus("error");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen bg-gray-100">
|
|
||||||
<Sidebar connectionStatus={connectionStatus} />
|
|
||||||
<div className="flex-1 flex flex-col overflow-hidden">
|
|
||||||
<h1 className="text-2xl font-bold p-4">MCP Inspector</h1>
|
|
||||||
<div className="flex-1 overflow-auto flex">
|
|
||||||
<div className="flex-1">
|
|
||||||
<div className="p-4 bg-white shadow-md m-4 rounded-md">
|
|
||||||
<h2 className="text-lg font-semibold mb-2">Connect MCP Server</h2>
|
|
||||||
<div className="flex space-x-2 mb-2">
|
|
||||||
<Select
|
|
||||||
value={transportType}
|
|
||||||
onValueChange={(value: "stdio" | "sse") =>
|
|
||||||
setTransportType(value)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-[180px]">
|
|
||||||
<SelectValue placeholder="Select transport type" />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="stdio">STDIO</SelectItem>
|
|
||||||
<SelectItem value="sse">SSE</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
{transportType === "stdio" ? (
|
|
||||||
<>
|
|
||||||
<Input
|
|
||||||
placeholder="Command"
|
|
||||||
value={command}
|
|
||||||
onChange={(e) => setCommand(e.target.value)}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
placeholder="Arguments (space-separated)"
|
|
||||||
value={args}
|
|
||||||
onChange={(e) => setArgs(e.target.value)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Input
|
|
||||||
placeholder="URL"
|
|
||||||
value={url}
|
|
||||||
onChange={(e) => setUrl(e.target.value)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Button onClick={connectMcpServer}>
|
|
||||||
<Play className="w-4 h-4 mr-2" />
|
|
||||||
Connect
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{mcpClient ? (
|
|
||||||
<Tabs defaultValue="resources" className="w-full p-4">
|
|
||||||
<TabsList className="mb-4 p-0">
|
|
||||||
<TabsTrigger value="resources">
|
|
||||||
<Files className="w-4 h-4 mr-2" />
|
|
||||||
Resources
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="prompts">
|
|
||||||
<MessageSquare className="w-4 h-4 mr-2" />
|
|
||||||
Prompts
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="requests" disabled>
|
|
||||||
<Send className="w-4 h-4 mr-2" />
|
|
||||||
Requests
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="notifications" disabled>
|
|
||||||
<Bell className="w-4 h-4 mr-2" />
|
|
||||||
Notifications
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="tools">
|
|
||||||
<Hammer className="w-4 h-4 mr-2" />
|
|
||||||
Tools
|
|
||||||
</TabsTrigger>
|
|
||||||
<TabsTrigger value="console" disabled>
|
|
||||||
<Terminal className="w-4 h-4 mr-2" />
|
|
||||||
Console
|
|
||||||
</TabsTrigger>
|
|
||||||
</TabsList>
|
|
||||||
|
|
||||||
<div className="w-full">
|
|
||||||
<ResourcesTab
|
|
||||||
resources={resources}
|
|
||||||
listResources={listResources}
|
|
||||||
readResource={readResource}
|
|
||||||
selectedResource={selectedResource}
|
|
||||||
setSelectedResource={setSelectedResource}
|
|
||||||
resourceContent={resourceContent}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
<NotificationsTab />
|
|
||||||
<PromptsTab
|
|
||||||
prompts={prompts}
|
|
||||||
listPrompts={listPrompts}
|
|
||||||
getPrompt={getPrompt}
|
|
||||||
selectedPrompt={selectedPrompt}
|
|
||||||
setSelectedPrompt={setSelectedPrompt}
|
|
||||||
promptContent={promptContent}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
<RequestsTab />
|
|
||||||
<ToolsTab
|
|
||||||
tools={tools}
|
|
||||||
listTools={listTools}
|
|
||||||
callTool={callTool}
|
|
||||||
selectedTool={selectedTool}
|
|
||||||
setSelectedTool={(tool) => {
|
|
||||||
setSelectedTool(tool);
|
|
||||||
setToolResult("");
|
|
||||||
}}
|
|
||||||
toolResult={toolResult}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
<ConsoleTab />
|
|
||||||
</div>
|
|
||||||
</Tabs>
|
|
||||||
) : (
|
|
||||||
<div className="flex items-center justify-center h-full">
|
|
||||||
<p className="text-lg text-gray-500">
|
|
||||||
Connect to an MCP server to start inspecting
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<History requestHistory={requestHistory} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
|
||||||
|
Before Width: | Height: | Size: 4.0 KiB |
@@ -1,12 +0,0 @@
|
|||||||
import { TabsContent } from "@/components/ui/tabs";
|
|
||||||
|
|
||||||
const ConsoleTab = () => (
|
|
||||||
<TabsContent value="console" className="h-96">
|
|
||||||
<div className="bg-gray-900 text-gray-100 p-4 rounded-lg h-full font-mono text-sm overflow-auto">
|
|
||||||
<div className="opacity-50">Welcome to MCP Client Console</div>
|
|
||||||
{/* Console output would go here */}
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default ConsoleTab;
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
import { useState } from "react";
|
|
||||||
import { Copy } from "lucide-react";
|
|
||||||
|
|
||||||
const History = ({
|
|
||||||
requestHistory,
|
|
||||||
}: {
|
|
||||||
requestHistory: Array<{ request: string; response: string | null }>;
|
|
||||||
}) => {
|
|
||||||
const [expandedRequests, setExpandedRequests] = useState<{
|
|
||||||
[key: number]: boolean;
|
|
||||||
}>({});
|
|
||||||
|
|
||||||
const toggleRequestExpansion = (index: number) => {
|
|
||||||
setExpandedRequests((prev) => ({ ...prev, [index]: !prev[index] }));
|
|
||||||
};
|
|
||||||
|
|
||||||
const copyToClipboard = (text: string) => {
|
|
||||||
navigator.clipboard.writeText(text);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="w-64 bg-white shadow-md p-4 overflow-y-auto">
|
|
||||||
<h2 className="text-lg font-semibold mb-4">History</h2>
|
|
||||||
<ul className="space-y-3">
|
|
||||||
{requestHistory
|
|
||||||
.slice()
|
|
||||||
.reverse()
|
|
||||||
.map((request, index) => (
|
|
||||||
<li
|
|
||||||
key={index}
|
|
||||||
className="text-sm text-gray-600 bg-gray-100 p-2 rounded"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="flex justify-between items-center cursor-pointer"
|
|
||||||
onClick={() =>
|
|
||||||
toggleRequestExpansion(requestHistory.length - 1 - index)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span className="font-mono">
|
|
||||||
{requestHistory.length - index}.{" "}
|
|
||||||
{JSON.parse(request.request).method}
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
{expandedRequests[requestHistory.length - 1 - index]
|
|
||||||
? "▼"
|
|
||||||
: "▶"}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{expandedRequests[requestHistory.length - 1 - index] && (
|
|
||||||
<>
|
|
||||||
<div className="mt-2">
|
|
||||||
<div className="flex justify-between items-center mb-1">
|
|
||||||
<span className="font-semibold text-blue-600">
|
|
||||||
Request:
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
onClick={() => copyToClipboard(request.request)}
|
|
||||||
className="text-blue-500 hover:text-blue-700"
|
|
||||||
>
|
|
||||||
<Copy size={16} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<pre className="whitespace-pre-wrap break-words bg-blue-50 p-2 rounded">
|
|
||||||
{JSON.stringify(JSON.parse(request.request), null, 2)}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
{request.response && (
|
|
||||||
<div className="mt-2">
|
|
||||||
<div className="flex justify-between items-center mb-1">
|
|
||||||
<span className="font-semibold text-green-600">
|
|
||||||
Response:
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
onClick={() => copyToClipboard(request.response!)}
|
|
||||||
className="text-blue-500 hover:text-blue-700"
|
|
||||||
>
|
|
||||||
<Copy size={16} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<pre className="whitespace-pre-wrap break-words bg-green-50 p-2 rounded">
|
|
||||||
{JSON.stringify(JSON.parse(request.response), null, 2)}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default History;
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
import { Button } from "./ui/button";
|
|
||||||
|
|
||||||
type ListPaneProps<T> = {
|
|
||||||
items: T[];
|
|
||||||
listItems: () => void;
|
|
||||||
setSelectedItem: (item: T) => void;
|
|
||||||
renderItem: (item: T) => React.ReactNode;
|
|
||||||
title: string;
|
|
||||||
buttonText: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ListPane = <T extends object>({
|
|
||||||
items,
|
|
||||||
listItems,
|
|
||||||
setSelectedItem,
|
|
||||||
renderItem,
|
|
||||||
title,
|
|
||||||
buttonText,
|
|
||||||
}: ListPaneProps<T>) => (
|
|
||||||
<div className="bg-white rounded-lg shadow">
|
|
||||||
<div className="p-4 border-b border-gray-200">
|
|
||||||
<h3 className="font-semibold">{title}</h3>
|
|
||||||
</div>
|
|
||||||
<div className="p-4">
|
|
||||||
<Button variant="outline" className="w-full mb-4" onClick={listItems}>
|
|
||||||
{buttonText}
|
|
||||||
</Button>
|
|
||||||
<div className="space-y-2">
|
|
||||||
{items.map((item, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="flex items-center p-2 rounded hover:bg-gray-50 cursor-pointer"
|
|
||||||
onClick={() => setSelectedItem(item)}
|
|
||||||
>
|
|
||||||
{renderItem(item)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default ListPane;
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { Bell } from "lucide-react";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
|
||||||
import { TabsContent } from "@/components/ui/tabs";
|
|
||||||
|
|
||||||
const NotificationsTab = () => (
|
|
||||||
<TabsContent value="notifications" className="space-y-4">
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex space-x-2">
|
|
||||||
<Input placeholder="Notification method" />
|
|
||||||
<Button>
|
|
||||||
<Bell className="w-4 h-4 mr-2" />
|
|
||||||
Send
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<Textarea
|
|
||||||
placeholder="Notification parameters (JSON)"
|
|
||||||
className="h-64 font-mono"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="bg-white rounded-lg shadow p-4">
|
|
||||||
<h3 className="font-semibold mb-4">Recent Notifications</h3>
|
|
||||||
<div className="space-y-2">
|
|
||||||
{/* Notification history would go here */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default NotificationsTab;
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
import { AlertCircle } from "lucide-react";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import { TabsContent } from "@/components/ui/tabs";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import ListPane from "./ListPane";
|
|
||||||
|
|
||||||
export type Prompt = {
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
arguments?: {
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
required?: boolean;
|
|
||||||
}[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const PromptsTab = ({
|
|
||||||
prompts,
|
|
||||||
listPrompts,
|
|
||||||
getPrompt,
|
|
||||||
selectedPrompt,
|
|
||||||
setSelectedPrompt,
|
|
||||||
promptContent,
|
|
||||||
error,
|
|
||||||
}: {
|
|
||||||
prompts: Prompt[];
|
|
||||||
listPrompts: () => void;
|
|
||||||
getPrompt: (name: string, args: Record<string, string>) => void;
|
|
||||||
selectedPrompt: Prompt | null;
|
|
||||||
setSelectedPrompt: (prompt: Prompt) => void;
|
|
||||||
promptContent: string;
|
|
||||||
error: string | null;
|
|
||||||
}) => {
|
|
||||||
const [promptArgs, setPromptArgs] = useState<Record<string, string>>({});
|
|
||||||
|
|
||||||
const handleInputChange = (argName: string, value: string) => {
|
|
||||||
setPromptArgs((prev) => ({ ...prev, [argName]: value }));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleGetPrompt = () => {
|
|
||||||
if (selectedPrompt) {
|
|
||||||
getPrompt(selectedPrompt.name, promptArgs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TabsContent value="prompts" className="grid grid-cols-2 gap-4">
|
|
||||||
<ListPane
|
|
||||||
items={prompts}
|
|
||||||
listItems={listPrompts}
|
|
||||||
setSelectedItem={(prompt) => {
|
|
||||||
setSelectedPrompt(prompt);
|
|
||||||
setPromptArgs({});
|
|
||||||
}}
|
|
||||||
renderItem={(prompt) => (
|
|
||||||
<>
|
|
||||||
<span className="flex-1">{prompt.name}</span>
|
|
||||||
<span className="text-sm text-gray-500">{prompt.description}</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
title="Prompts"
|
|
||||||
buttonText="List Prompts"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="bg-white rounded-lg shadow">
|
|
||||||
<div className="p-4 border-b border-gray-200">
|
|
||||||
<h3 className="font-semibold">
|
|
||||||
{selectedPrompt ? selectedPrompt.name : "Select a prompt"}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div className="p-4">
|
|
||||||
{error ? (
|
|
||||||
<Alert variant="destructive">
|
|
||||||
<AlertCircle className="h-4 w-4" />
|
|
||||||
<AlertTitle>Error</AlertTitle>
|
|
||||||
<AlertDescription>{error}</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
) : selectedPrompt ? (
|
|
||||||
<div className="space-y-4">
|
|
||||||
{selectedPrompt.description && (
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
{selectedPrompt.description}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{selectedPrompt.arguments?.map((arg) => (
|
|
||||||
<div key={arg.name}>
|
|
||||||
<Label htmlFor={arg.name}>{arg.name}</Label>
|
|
||||||
<Input
|
|
||||||
id={arg.name}
|
|
||||||
placeholder={`Enter ${arg.name}`}
|
|
||||||
value={promptArgs[arg.name] || ""}
|
|
||||||
onChange={(e) =>
|
|
||||||
handleInputChange(arg.name, e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{arg.description && (
|
|
||||||
<p className="text-xs text-gray-500 mt-1">
|
|
||||||
{arg.description}
|
|
||||||
{arg.required && (
|
|
||||||
<span className="text-xs mt-1 ml-1">(Required)</span>
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
<Button onClick={handleGetPrompt} className="w-full">
|
|
||||||
Get Prompt
|
|
||||||
</Button>
|
|
||||||
{promptContent && (
|
|
||||||
<Textarea
|
|
||||||
value={promptContent}
|
|
||||||
readOnly
|
|
||||||
className="h-64 font-mono"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Alert>
|
|
||||||
<AlertDescription>
|
|
||||||
Select a prompt from the list to view and use it
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default PromptsTab;
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { TabsContent } from "@/components/ui/tabs";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
|
||||||
import { Send } from "lucide-react";
|
|
||||||
|
|
||||||
const RequestsTab = () => (
|
|
||||||
<TabsContent value="requests" className="space-y-4">
|
|
||||||
<div className="grid grid-cols-2 gap-4">
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex space-x-2">
|
|
||||||
<Input placeholder="Method name" />
|
|
||||||
<Button>
|
|
||||||
<Send className="w-4 h-4 mr-2" />
|
|
||||||
Send
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<Textarea
|
|
||||||
placeholder="Request parameters (JSON)"
|
|
||||||
className="h-64 font-mono"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="bg-gray-50 p-4 rounded-lg h-96 font-mono text-sm overflow-auto">
|
|
||||||
<div className="text-gray-500 mb-2">Response:</div>
|
|
||||||
{/* Response content would go here */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default RequestsTab;
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
import { FileText, ChevronRight, AlertCircle, RefreshCw } from "lucide-react";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import { TabsContent } from "@/components/ui/tabs";
|
|
||||||
import ListPane from "./ListPane";
|
|
||||||
|
|
||||||
export type Resource = {
|
|
||||||
uri: string;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ResourcesTab = ({
|
|
||||||
resources,
|
|
||||||
listResources,
|
|
||||||
readResource,
|
|
||||||
selectedResource,
|
|
||||||
setSelectedResource,
|
|
||||||
resourceContent,
|
|
||||||
error,
|
|
||||||
}: {
|
|
||||||
resources: Resource[];
|
|
||||||
listResources: () => void;
|
|
||||||
readResource: (uri: string) => void;
|
|
||||||
selectedResource: Resource | null;
|
|
||||||
setSelectedResource: (resource: Resource) => void;
|
|
||||||
resourceContent: string;
|
|
||||||
error: string | null;
|
|
||||||
}) => (
|
|
||||||
<TabsContent value="resources" className="grid grid-cols-2 gap-4">
|
|
||||||
<ListPane
|
|
||||||
items={resources}
|
|
||||||
listItems={listResources}
|
|
||||||
setSelectedItem={(resource) => {
|
|
||||||
setSelectedResource(resource);
|
|
||||||
readResource(resource.uri);
|
|
||||||
}}
|
|
||||||
renderItem={(resource) => (
|
|
||||||
<div className="flex items-center w-full">
|
|
||||||
<FileText className="w-4 h-4 mr-2 flex-shrink-0 text-gray-500" />
|
|
||||||
<span className="flex-1 truncate" title={resource.uri}>
|
|
||||||
{resource.name}
|
|
||||||
</span>
|
|
||||||
<ChevronRight className="w-4 h-4 flex-shrink-0 text-gray-400" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
title="Resources"
|
|
||||||
buttonText="List Resources"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="bg-white rounded-lg shadow">
|
|
||||||
<div className="p-4 border-b border-gray-200 flex justify-between items-center">
|
|
||||||
<h3 className="font-semibold truncate" title={selectedResource?.name}>
|
|
||||||
{selectedResource ? selectedResource.name : "Select a resource"}
|
|
||||||
</h3>
|
|
||||||
{selectedResource && (
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => readResource(selectedResource.uri)}
|
|
||||||
>
|
|
||||||
<RefreshCw className="w-4 h-4 mr-2" />
|
|
||||||
Refresh
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="p-4">
|
|
||||||
{error ? (
|
|
||||||
<Alert variant="destructive">
|
|
||||||
<AlertCircle className="h-4 w-4" />
|
|
||||||
<AlertTitle>Error</AlertTitle>
|
|
||||||
<AlertDescription>{error}</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
) : selectedResource ? (
|
|
||||||
<pre className="bg-gray-50 p-4 rounded text-sm overflow-auto max-h-96 whitespace-pre-wrap break-words">
|
|
||||||
{resourceContent}
|
|
||||||
</pre>
|
|
||||||
) : (
|
|
||||||
<Alert>
|
|
||||||
<AlertDescription>
|
|
||||||
Select a resource from the list to view its contents
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default ResourcesTab;
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import { Menu, Settings } from "lucide-react";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
|
|
||||||
const Sidebar = ({ connectionStatus }: { connectionStatus: string }) => (
|
|
||||||
<div className="w-64 bg-white border-r border-gray-200">
|
|
||||||
<div className="flex items-center p-4 border-b border-gray-200">
|
|
||||||
<Menu className="w-6 h-6 text-gray-500" />
|
|
||||||
<h1 className="ml-2 text-lg font-semibold">MCP Inspector</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="p-4">
|
|
||||||
<div className="flex items-center space-x-2 mb-4">
|
|
||||||
<div
|
|
||||||
className={`w-2 h-2 rounded-full ${
|
|
||||||
connectionStatus === "connected"
|
|
||||||
? "bg-green-500"
|
|
||||||
: connectionStatus === "error"
|
|
||||||
? "bg-red-500"
|
|
||||||
: "bg-gray-500"
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
<span className="text-sm text-gray-600">
|
|
||||||
{connectionStatus === "connected"
|
|
||||||
? "Connected"
|
|
||||||
: connectionStatus === "error"
|
|
||||||
? "Connection Error"
|
|
||||||
: "Disconnected"}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button variant="outline" className="w-full justify-start">
|
|
||||||
<Settings className="w-4 h-4 mr-2" />
|
|
||||||
Connection Settings
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default Sidebar;
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
import { TabsContent } from "@/components/ui/tabs";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Send, AlertCircle } from "lucide-react";
|
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
||||||
import { Tool } from "mcp-typescript/types.js";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import ListPane from "./ListPane";
|
|
||||||
|
|
||||||
const ToolsTab = ({
|
|
||||||
tools,
|
|
||||||
listTools,
|
|
||||||
callTool,
|
|
||||||
selectedTool,
|
|
||||||
setSelectedTool,
|
|
||||||
toolResult,
|
|
||||||
error,
|
|
||||||
}: {
|
|
||||||
tools: Tool[];
|
|
||||||
listTools: () => void;
|
|
||||||
callTool: (name: string, params: Record<string, unknown>) => void;
|
|
||||||
selectedTool: Tool | null;
|
|
||||||
setSelectedTool: (tool: Tool) => void;
|
|
||||||
toolResult: string;
|
|
||||||
error: string | null;
|
|
||||||
}) => {
|
|
||||||
const [params, setParams] = useState<Record<string, unknown>>({});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TabsContent value="tools" className="grid grid-cols-2 gap-4">
|
|
||||||
<ListPane
|
|
||||||
items={tools}
|
|
||||||
listItems={listTools}
|
|
||||||
setSelectedItem={setSelectedTool}
|
|
||||||
renderItem={(tool) => (
|
|
||||||
<>
|
|
||||||
<span className="flex-1">{tool.name}</span>
|
|
||||||
<span className="text-sm text-gray-500">{tool.description}</span>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
title="Tools"
|
|
||||||
buttonText="List Tools"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="bg-white rounded-lg shadow">
|
|
||||||
<div className="p-4 border-b border-gray-200">
|
|
||||||
<h3 className="font-semibold">
|
|
||||||
{selectedTool ? selectedTool.name : "Select a tool"}
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div className="p-4">
|
|
||||||
{error ? (
|
|
||||||
<Alert variant="destructive">
|
|
||||||
<AlertCircle className="h-4 w-4" />
|
|
||||||
<AlertTitle>Error</AlertTitle>
|
|
||||||
<AlertDescription>{error}</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
) : selectedTool ? (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<p className="text-sm text-gray-600">
|
|
||||||
{selectedTool.description}
|
|
||||||
</p>
|
|
||||||
{Object.entries(selectedTool.inputSchema.properties).map(
|
|
||||||
([key, value]) => (
|
|
||||||
<div key={key}>
|
|
||||||
<Label
|
|
||||||
htmlFor={key}
|
|
||||||
className="block text-sm font-medium text-gray-700"
|
|
||||||
>
|
|
||||||
{key}
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
type={value.type === "number" ? "number" : "text"}
|
|
||||||
id={key}
|
|
||||||
name={key}
|
|
||||||
placeholder={value.description}
|
|
||||||
onChange={(e) =>
|
|
||||||
setParams({
|
|
||||||
...params,
|
|
||||||
[key]:
|
|
||||||
value.type === "number"
|
|
||||||
? Number(e.target.value)
|
|
||||||
: e.target.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
<Button onClick={() => callTool(selectedTool.name, params)}>
|
|
||||||
<Send className="w-4 h-4 mr-2" />
|
|
||||||
Run Tool
|
|
||||||
</Button>
|
|
||||||
{toolResult && (
|
|
||||||
<>
|
|
||||||
<h4 className="font-semibold mb-2">Tool Result:</h4>
|
|
||||||
<pre className="bg-gray-50 p-4 rounded text-sm overflow-auto max-h-64">
|
|
||||||
{toolResult}
|
|
||||||
</pre>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Alert>
|
|
||||||
<AlertDescription>
|
|
||||||
Select a tool from the list to view its details and run it
|
|
||||||
</AlertDescription>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ToolsTab;
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const alertVariants = cva(
|
|
||||||
"relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
|
|
||||||
{
|
|
||||||
variants: {
|
|
||||||
variant: {
|
|
||||||
default: "bg-background text-foreground",
|
|
||||||
destructive:
|
|
||||||
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
variant: "default",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const Alert = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
|
|
||||||
>(({ className, variant, ...props }, ref) => (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
role="alert"
|
|
||||||
className={cn(alertVariants({ variant }), className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
Alert.displayName = "Alert"
|
|
||||||
|
|
||||||
const AlertTitle = React.forwardRef<
|
|
||||||
HTMLParagraphElement,
|
|
||||||
React.HTMLAttributes<HTMLHeadingElement>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<h5
|
|
||||||
ref={ref}
|
|
||||||
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
AlertTitle.displayName = "AlertTitle"
|
|
||||||
|
|
||||||
const AlertDescription = React.forwardRef<
|
|
||||||
HTMLParagraphElement,
|
|
||||||
React.HTMLAttributes<HTMLParagraphElement>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
className={cn("text-sm [&_p]:leading-relaxed", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
AlertDescription.displayName = "AlertDescription"
|
|
||||||
|
|
||||||
export { Alert, AlertTitle, AlertDescription }
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
import { Slot } from "@radix-ui/react-slot"
|
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const buttonVariants = cva(
|
|
||||||
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
|
|
||||||
{
|
|
||||||
variants: {
|
|
||||||
variant: {
|
|
||||||
default:
|
|
||||||
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
||||||
destructive:
|
|
||||||
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
||||||
outline:
|
|
||||||
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
||||||
secondary:
|
|
||||||
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
||||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
default: "h-9 px-4 py-2",
|
|
||||||
sm: "h-8 rounded-md px-3 text-xs",
|
|
||||||
lg: "h-10 rounded-md px-8",
|
|
||||||
icon: "h-9 w-9",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
variant: "default",
|
|
||||||
size: "default",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export interface ButtonProps
|
|
||||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
||||||
VariantProps<typeof buttonVariants> {
|
|
||||||
asChild?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
||||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
||||||
const Comp = asChild ? Slot : "button"
|
|
||||||
return (
|
|
||||||
<Comp
|
|
||||||
className={cn(buttonVariants({ variant, size, className }))}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
Button.displayName = "Button"
|
|
||||||
|
|
||||||
export { Button, buttonVariants }
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
export interface InputProps
|
|
||||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
|
||||||
|
|
||||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
||||||
({ className, type, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<input
|
|
||||||
type={type}
|
|
||||||
className={cn(
|
|
||||||
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
Input.displayName = "Input"
|
|
||||||
|
|
||||||
export { Input }
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const labelVariants = cva(
|
|
||||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
||||||
)
|
|
||||||
|
|
||||||
const Label = React.forwardRef<
|
|
||||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
|
||||||
VariantProps<typeof labelVariants>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<LabelPrimitive.Root
|
|
||||||
ref={ref}
|
|
||||||
className={cn(labelVariants(), className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
Label.displayName = LabelPrimitive.Root.displayName
|
|
||||||
|
|
||||||
export { Label }
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
import {
|
|
||||||
CaretSortIcon,
|
|
||||||
CheckIcon,
|
|
||||||
ChevronDownIcon,
|
|
||||||
ChevronUpIcon,
|
|
||||||
} from "@radix-ui/react-icons"
|
|
||||||
import * as SelectPrimitive from "@radix-ui/react-select"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const Select = SelectPrimitive.Root
|
|
||||||
|
|
||||||
const SelectGroup = SelectPrimitive.Group
|
|
||||||
|
|
||||||
const SelectValue = SelectPrimitive.Value
|
|
||||||
|
|
||||||
const SelectTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Trigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<SelectPrimitive.Icon asChild>
|
|
||||||
<CaretSortIcon className="h-4 w-4 opacity-50" />
|
|
||||||
</SelectPrimitive.Icon>
|
|
||||||
</SelectPrimitive.Trigger>
|
|
||||||
))
|
|
||||||
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
|
|
||||||
|
|
||||||
const SelectScrollUpButton = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.ScrollUpButton
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex cursor-default items-center justify-center py-1",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ChevronUpIcon />
|
|
||||||
</SelectPrimitive.ScrollUpButton>
|
|
||||||
))
|
|
||||||
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
|
|
||||||
|
|
||||||
const SelectScrollDownButton = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.ScrollDownButton
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex cursor-default items-center justify-center py-1",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ChevronDownIcon />
|
|
||||||
</SelectPrimitive.ScrollDownButton>
|
|
||||||
))
|
|
||||||
SelectScrollDownButton.displayName =
|
|
||||||
SelectPrimitive.ScrollDownButton.displayName
|
|
||||||
|
|
||||||
const SelectContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
||||||
>(({ className, children, position = "popper", ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Portal>
|
|
||||||
<SelectPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
position === "popper" &&
|
|
||||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
position={position}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<SelectScrollUpButton />
|
|
||||||
<SelectPrimitive.Viewport
|
|
||||||
className={cn(
|
|
||||||
"p-1",
|
|
||||||
position === "popper" &&
|
|
||||||
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</SelectPrimitive.Viewport>
|
|
||||||
<SelectScrollDownButton />
|
|
||||||
</SelectPrimitive.Content>
|
|
||||||
</SelectPrimitive.Portal>
|
|
||||||
))
|
|
||||||
SelectContent.displayName = SelectPrimitive.Content.displayName
|
|
||||||
|
|
||||||
const SelectLabel = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Label>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Label
|
|
||||||
ref={ref}
|
|
||||||
className={cn("px-2 py-1.5 text-sm font-semibold", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
SelectLabel.displayName = SelectPrimitive.Label.displayName
|
|
||||||
|
|
||||||
const SelectItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Item>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Item
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
||||||
<SelectPrimitive.ItemIndicator>
|
|
||||||
<CheckIcon className="h-4 w-4" />
|
|
||||||
</SelectPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
||||||
</SelectPrimitive.Item>
|
|
||||||
))
|
|
||||||
SelectItem.displayName = SelectPrimitive.Item.displayName
|
|
||||||
|
|
||||||
const SelectSeparator = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Separator>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Separator
|
|
||||||
ref={ref}
|
|
||||||
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
|
|
||||||
|
|
||||||
export {
|
|
||||||
Select,
|
|
||||||
SelectGroup,
|
|
||||||
SelectValue,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectContent,
|
|
||||||
SelectLabel,
|
|
||||||
SelectItem,
|
|
||||||
SelectSeparator,
|
|
||||||
SelectScrollUpButton,
|
|
||||||
SelectScrollDownButton,
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const Tabs = TabsPrimitive.Root
|
|
||||||
|
|
||||||
const TabsList = React.forwardRef<
|
|
||||||
React.ElementRef<typeof TabsPrimitive.List>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<TabsPrimitive.List
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
TabsList.displayName = TabsPrimitive.List.displayName
|
|
||||||
|
|
||||||
const TabsTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<TabsPrimitive.Trigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
|
|
||||||
|
|
||||||
const TabsContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<TabsPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
TabsContent.displayName = TabsPrimitive.Content.displayName
|
|
||||||
|
|
||||||
export { Tabs, TabsList, TabsTrigger, TabsContent }
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import * as React from "react"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
export interface TextareaProps
|
|
||||||
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
|
||||||
|
|
||||||
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<textarea
|
|
||||||
className={cn(
|
|
||||||
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
Textarea.displayName = "Textarea"
|
|
||||||
|
|
||||||
export { Textarea }
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
:root {
|
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
color-scheme: light dark;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
background-color: #242424;
|
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #646cff;
|
|
||||||
text-decoration: inherit;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #535bf2;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 3.2em;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.25s;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
border-color: #646cff;
|
|
||||||
}
|
|
||||||
button:focus,
|
|
||||||
button:focus-visible {
|
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
|
||||||
:root {
|
|
||||||
color: #213547;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #747bff;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer base {
|
|
||||||
:root {
|
|
||||||
--background: 0 0% 100%;
|
|
||||||
--foreground: 222.2 84% 4.9%;
|
|
||||||
--card: 0 0% 100%;
|
|
||||||
--card-foreground: 222.2 84% 4.9%;
|
|
||||||
--popover: 0 0% 100%;
|
|
||||||
--popover-foreground: 222.2 84% 4.9%;
|
|
||||||
--primary: 222.2 47.4% 11.2%;
|
|
||||||
--primary-foreground: 210 40% 98%;
|
|
||||||
--secondary: 210 40% 96.1%;
|
|
||||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
||||||
--muted: 210 40% 96.1%;
|
|
||||||
--muted-foreground: 215.4 16.3% 46.9%;
|
|
||||||
--accent: 210 40% 96.1%;
|
|
||||||
--accent-foreground: 222.2 47.4% 11.2%;
|
|
||||||
--destructive: 0 84.2% 60.2%;
|
|
||||||
--destructive-foreground: 210 40% 98%;
|
|
||||||
--border: 214.3 31.8% 91.4%;
|
|
||||||
--input: 214.3 31.8% 91.4%;
|
|
||||||
--ring: 222.2 84% 4.9%;
|
|
||||||
--chart-1: 12 76% 61%;
|
|
||||||
--chart-2: 173 58% 39%;
|
|
||||||
--chart-3: 197 37% 24%;
|
|
||||||
--chart-4: 43 74% 66%;
|
|
||||||
--chart-5: 27 87% 67%;
|
|
||||||
--radius: 0.5rem;
|
|
||||||
}
|
|
||||||
.dark {
|
|
||||||
--background: 222.2 84% 4.9%;
|
|
||||||
--foreground: 210 40% 98%;
|
|
||||||
--card: 222.2 84% 4.9%;
|
|
||||||
--card-foreground: 210 40% 98%;
|
|
||||||
--popover: 222.2 84% 4.9%;
|
|
||||||
--popover-foreground: 210 40% 98%;
|
|
||||||
--primary: 210 40% 98%;
|
|
||||||
--primary-foreground: 222.2 47.4% 11.2%;
|
|
||||||
--secondary: 217.2 32.6% 17.5%;
|
|
||||||
--secondary-foreground: 210 40% 98%;
|
|
||||||
--muted: 217.2 32.6% 17.5%;
|
|
||||||
--muted-foreground: 215 20.2% 65.1%;
|
|
||||||
--accent: 217.2 32.6% 17.5%;
|
|
||||||
--accent-foreground: 210 40% 98%;
|
|
||||||
--destructive: 0 62.8% 30.6%;
|
|
||||||
--destructive-foreground: 210 40% 98%;
|
|
||||||
--border: 217.2 32.6% 17.5%;
|
|
||||||
--input: 217.2 32.6% 17.5%;
|
|
||||||
--ring: 212.7 26.8% 83.9%;
|
|
||||||
--chart-1: 220 70% 50%;
|
|
||||||
--chart-2: 160 60% 45%;
|
|
||||||
--chart-3: 30 80% 55%;
|
|
||||||
--chart-4: 280 65% 60%;
|
|
||||||
--chart-5: 340 75% 55%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer base {
|
|
||||||
* {
|
|
||||||
@apply border-border;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
@apply bg-background text-foreground;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { clsx, type ClassValue } from "clsx"
|
|
||||||
import { twMerge } from "tailwind-merge"
|
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
|
||||||
return twMerge(clsx(inputs))
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { StrictMode } from "react";
|
|
||||||
import { createRoot } from "react-dom/client";
|
|
||||||
import App from "./App.tsx";
|
|
||||||
import "./index.css";
|
|
||||||
|
|
||||||
createRoot(document.getElementById("root")!).render(
|
|
||||||
<StrictMode>
|
|
||||||
<App />
|
|
||||||
</StrictMode>,
|
|
||||||
);
|
|
||||||
1
client/src/vite-env.d.ts
vendored
1
client/src/vite-env.d.ts
vendored
@@ -1 +0,0 @@
|
|||||||
/// <reference types="vite/client" />
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
export default {
|
|
||||||
darkMode: ["class"],
|
|
||||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
borderRadius: {
|
|
||||||
lg: "var(--radius)",
|
|
||||||
md: "calc(var(--radius) - 2px)",
|
|
||||||
sm: "calc(var(--radius) - 4px)",
|
|
||||||
},
|
|
||||||
colors: {
|
|
||||||
background: "hsl(var(--background))",
|
|
||||||
foreground: "hsl(var(--foreground))",
|
|
||||||
card: {
|
|
||||||
DEFAULT: "hsl(var(--card))",
|
|
||||||
foreground: "hsl(var(--card-foreground))",
|
|
||||||
},
|
|
||||||
popover: {
|
|
||||||
DEFAULT: "hsl(var(--popover))",
|
|
||||||
foreground: "hsl(var(--popover-foreground))",
|
|
||||||
},
|
|
||||||
primary: {
|
|
||||||
DEFAULT: "hsl(var(--primary))",
|
|
||||||
foreground: "hsl(var(--primary-foreground))",
|
|
||||||
},
|
|
||||||
secondary: {
|
|
||||||
DEFAULT: "hsl(var(--secondary))",
|
|
||||||
foreground: "hsl(var(--secondary-foreground))",
|
|
||||||
},
|
|
||||||
muted: {
|
|
||||||
DEFAULT: "hsl(var(--muted))",
|
|
||||||
foreground: "hsl(var(--muted-foreground))",
|
|
||||||
},
|
|
||||||
accent: {
|
|
||||||
DEFAULT: "hsl(var(--accent))",
|
|
||||||
foreground: "hsl(var(--accent-foreground))",
|
|
||||||
},
|
|
||||||
destructive: {
|
|
||||||
DEFAULT: "hsl(var(--destructive))",
|
|
||||||
foreground: "hsl(var(--destructive-foreground))",
|
|
||||||
},
|
|
||||||
border: "hsl(var(--border))",
|
|
||||||
input: "hsl(var(--input))",
|
|
||||||
ring: "hsl(var(--ring))",
|
|
||||||
chart: {
|
|
||||||
1: "hsl(var(--chart-1))",
|
|
||||||
2: "hsl(var(--chart-2))",
|
|
||||||
3: "hsl(var(--chart-3))",
|
|
||||||
4: "hsl(var(--chart-4))",
|
|
||||||
5: "hsl(var(--chart-5))",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [require("tailwindcss-animate")],
|
|
||||||
};
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"@/*": [
|
|
||||||
"./src/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
"target": "ES2020",
|
|
||||||
"useDefineForClassFields": true,
|
|
||||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"skipLibCheck": true,
|
|
||||||
|
|
||||||
/* Bundler mode */
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"moduleDetection": "force",
|
|
||||||
"noEmit": true,
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
|
|
||||||
/* Linting */
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"noFallthroughCasesInSwitch": true
|
|
||||||
},
|
|
||||||
"include": ["src"]
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"files": [],
|
|
||||||
"references": [
|
|
||||||
{ "path": "./tsconfig.app.json" },
|
|
||||||
{ "path": "./tsconfig.node.json" }
|
|
||||||
],
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ES2022",
|
|
||||||
"lib": ["ES2023"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"skipLibCheck": true,
|
|
||||||
|
|
||||||
/* Bundler mode */
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"moduleDetection": "force",
|
|
||||||
"noEmit": true,
|
|
||||||
|
|
||||||
/* Linting */
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"noFallthroughCasesInSwitch": true
|
|
||||||
},
|
|
||||||
"include": ["vite.config.ts"]
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"root":["./vite.config.ts"],"version":"5.6.2"}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import path from "path";
|
|
||||||
import { defineConfig } from "vite";
|
|
||||||
import react from "@vitejs/plugin-react";
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [react()],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
"@": path.resolve(__dirname, "./src"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
0
packages/mcp-typescript/dist/cli.d.ts → dist/cli.d.ts
generated
vendored
0
packages/mcp-typescript/dist/cli.d.ts → dist/cli.d.ts
generated
vendored
0
packages/mcp-typescript/dist/cli.d.ts.map → dist/cli.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/cli.d.ts.map → dist/cli.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/cli.js → dist/cli.js
generated
vendored
0
packages/mcp-typescript/dist/cli.js → dist/cli.js
generated
vendored
0
packages/mcp-typescript/dist/cli.js.map → dist/cli.js.map
generated
vendored
0
packages/mcp-typescript/dist/cli.js.map → dist/cli.js.map
generated
vendored
0
packages/mcp-typescript/dist/client/index.d.ts → dist/client/index.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/index.d.ts → dist/client/index.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/index.d.ts.map → dist/client/index.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/client/index.d.ts.map → dist/client/index.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/client/index.js → dist/client/index.js
generated
vendored
0
packages/mcp-typescript/dist/client/index.js → dist/client/index.js
generated
vendored
0
packages/mcp-typescript/dist/client/index.js.map → dist/client/index.js.map
generated
vendored
0
packages/mcp-typescript/dist/client/index.js.map → dist/client/index.js.map
generated
vendored
0
packages/mcp-typescript/dist/client/sse.d.ts → dist/client/sse.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/sse.d.ts → dist/client/sse.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/sse.d.ts.map → dist/client/sse.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/client/sse.d.ts.map → dist/client/sse.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/client/sse.js → dist/client/sse.js
generated
vendored
0
packages/mcp-typescript/dist/client/sse.js → dist/client/sse.js
generated
vendored
0
packages/mcp-typescript/dist/client/sse.js.map → dist/client/sse.js.map
generated
vendored
0
packages/mcp-typescript/dist/client/sse.js.map → dist/client/sse.js.map
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.d.ts → dist/client/stdio.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.d.ts → dist/client/stdio.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.d.ts.map → dist/client/stdio.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.d.ts.map → dist/client/stdio.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.js → dist/client/stdio.js
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.js → dist/client/stdio.js
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.js.map → dist/client/stdio.js.map
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.js.map → dist/client/stdio.js.map
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.test.d.ts → dist/client/stdio.test.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.test.d.ts → dist/client/stdio.test.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.test.js → dist/client/stdio.test.js
generated
vendored
0
packages/mcp-typescript/dist/client/stdio.test.js → dist/client/stdio.test.js
generated
vendored
0
packages/mcp-typescript/dist/client/websocket.d.ts → dist/client/websocket.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/websocket.d.ts → dist/client/websocket.d.ts
generated
vendored
0
packages/mcp-typescript/dist/client/websocket.js → dist/client/websocket.js
generated
vendored
0
packages/mcp-typescript/dist/client/websocket.js → dist/client/websocket.js
generated
vendored
0
packages/mcp-typescript/dist/client/websocket.js.map → dist/client/websocket.js.map
generated
vendored
0
packages/mcp-typescript/dist/client/websocket.js.map → dist/client/websocket.js.map
generated
vendored
0
packages/mcp-typescript/dist/server/index.d.ts → dist/server/index.d.ts
generated
vendored
0
packages/mcp-typescript/dist/server/index.d.ts → dist/server/index.d.ts
generated
vendored
0
packages/mcp-typescript/dist/server/index.d.ts.map → dist/server/index.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/server/index.d.ts.map → dist/server/index.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/server/index.js → dist/server/index.js
generated
vendored
0
packages/mcp-typescript/dist/server/index.js → dist/server/index.js
generated
vendored
0
packages/mcp-typescript/dist/server/index.js.map → dist/server/index.js.map
generated
vendored
0
packages/mcp-typescript/dist/server/index.js.map → dist/server/index.js.map
generated
vendored
0
packages/mcp-typescript/dist/server/sse.d.ts → dist/server/sse.d.ts
generated
vendored
0
packages/mcp-typescript/dist/server/sse.d.ts → dist/server/sse.d.ts
generated
vendored
0
packages/mcp-typescript/dist/server/sse.d.ts.map → dist/server/sse.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/server/sse.d.ts.map → dist/server/sse.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/server/sse.js → dist/server/sse.js
generated
vendored
0
packages/mcp-typescript/dist/server/sse.js → dist/server/sse.js
generated
vendored
0
packages/mcp-typescript/dist/server/sse.js.map → dist/server/sse.js.map
generated
vendored
0
packages/mcp-typescript/dist/server/sse.js.map → dist/server/sse.js.map
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.d.ts → dist/server/stdio.d.ts
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.d.ts → dist/server/stdio.d.ts
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.d.ts.map → dist/server/stdio.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.d.ts.map → dist/server/stdio.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.js → dist/server/stdio.js
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.js → dist/server/stdio.js
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.js.map → dist/server/stdio.js.map
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.js.map → dist/server/stdio.js.map
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.test.d.ts → dist/server/stdio.test.d.ts
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.test.d.ts → dist/server/stdio.test.d.ts
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.test.js → dist/server/stdio.test.js
generated
vendored
0
packages/mcp-typescript/dist/server/stdio.test.js → dist/server/stdio.test.js
generated
vendored
0
packages/mcp-typescript/dist/shared/protocol.d.ts → dist/shared/protocol.d.ts
generated
vendored
0
packages/mcp-typescript/dist/shared/protocol.d.ts → dist/shared/protocol.d.ts
generated
vendored
0
packages/mcp-typescript/dist/shared/protocol.js → dist/shared/protocol.js
generated
vendored
0
packages/mcp-typescript/dist/shared/protocol.js → dist/shared/protocol.js
generated
vendored
0
packages/mcp-typescript/dist/shared/protocol.js.map → dist/shared/protocol.js.map
generated
vendored
0
packages/mcp-typescript/dist/shared/protocol.js.map → dist/shared/protocol.js.map
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.d.ts → dist/shared/stdio.d.ts
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.d.ts → dist/shared/stdio.d.ts
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.d.ts.map → dist/shared/stdio.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.d.ts.map → dist/shared/stdio.d.ts.map
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.js → dist/shared/stdio.js
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.js → dist/shared/stdio.js
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.js.map → dist/shared/stdio.js.map
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.js.map → dist/shared/stdio.js.map
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.test.d.ts → dist/shared/stdio.test.d.ts
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.test.d.ts → dist/shared/stdio.test.d.ts
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.test.js → dist/shared/stdio.test.js
generated
vendored
0
packages/mcp-typescript/dist/shared/stdio.test.js → dist/shared/stdio.test.js
generated
vendored
0
packages/mcp-typescript/dist/shared/transport.d.ts → dist/shared/transport.d.ts
generated
vendored
0
packages/mcp-typescript/dist/shared/transport.d.ts → dist/shared/transport.d.ts
generated
vendored
0
packages/mcp-typescript/dist/shared/transport.js → dist/shared/transport.js
generated
vendored
0
packages/mcp-typescript/dist/shared/transport.js → dist/shared/transport.js
generated
vendored
0
packages/mcp-typescript/dist/shared/transport.js.map → dist/shared/transport.js.map
generated
vendored
0
packages/mcp-typescript/dist/shared/transport.js.map → dist/shared/transport.js.map
generated
vendored
2916
packages/mcp-typescript/dist/types.d.ts → dist/types.d.ts
generated
vendored
2916
packages/mcp-typescript/dist/types.d.ts → dist/types.d.ts
generated
vendored
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user