jupyter-kernel-mcp
Provides tools for managing and executing code in Jupyter kernels with persistent state, supporting Python, TypeScript, and JavaScript.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@jupyter-kernel-mcpLoad the iris dataset and display summary statistics"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Jupyter Kernel MCP
A Model Context Protocol (MCP) server that provides stateful Jupyter kernel development with multi-language support (Python, TypeScript, JavaScript) for AI agents and assistants.
Table of contents
Related MCP server: JupyterMCP
Project description
With Jupyter Kernel MCP you can execute Python, TypeScript, and JavaScript code in persistent, isolated environments that maintain state between executions—perfect for AI agents performing complex data analysis and development workflows.
Jupyter Kernel MCP helps you build stateful AI agent workflows that can load datasets, perform transformations, and analyze results across multiple interactions without losing variables or computed state.
Unlike traditional stateless code execution, Jupyter Kernel MCP preserves variables, imports, and computed results between AI agent messages, enabling sophisticated multi-step data science workflows.
Key Features
🔄 Persistent State: Variables and imports persist between code executions
🌐 Multi-Language Support: Python, TypeScript, and JavaScript kernels
🚀 Multi-Kernel Support: Create and manage multiple isolated kernel environments
🤖 AI-Agent Ready: Seamless integration with Claude Code and other MCP clients
📊 Data Science Workflows: Perfect for iterative data analysis and exploration
⚡ Fast Communication: Direct socket-based communication with Jupyter kernels
🛠 Easy Management: Simple kernel lifecycle management (start, stop, reset, list)
🔗 Unified API: Single interface for all languages - no separate tools needed
Who this project is for
This project is intended for AI developers, data scientists, and automation engineers who want to build intelligent agents that can perform stateful data analysis and complex computational workflows.
Perfect for:
Building AI agents that analyze datasets across multiple interactions
Creating persistent computational environments for LLMs
Developing stateful data science workflows with AI assistants
Prototyping and exploring APIs with maintained context
Full-stack development with TypeScript/JavaScript and Python
Educational environments teaching multiple programming languages
Project dependencies
Before using Jupyter Kernel MCP, ensure you have:
Python 3.10 or higher - Required for MCP SDK compatibility
Claude Code, Cline, or another MCP client - To interact with the server
Jupyter dependencies - Automatically installed with the package
Node.js (for TypeScript/JavaScript) - Required for TSLAB kernels (optional)
TSLAB - TypeScript/JavaScript kernel support (optional)
Instructions for using Jupyter Kernel MCP
Get started with Jupyter Kernel MCP by installing the package and adding it to your MCP client.
Install Jupyter Kernel MCP
From PyPI (Recommended)
Install using pip:
pip install jupyter-kernel-mcpOr using uv:
uv add jupyter-kernel-mcpFrom GitHub (Development Version)
To install the latest development version directly from GitHub:
uv tool install git+https://github.com/codewithcheese/jupyter-kernel-mcp.gitVerify Installation
jupyter-kernel-mcp --helpOptional: Install TSLAB for TypeScript/JavaScript Support
To enable TypeScript and JavaScript kernels:
# Install TSLAB globally
npm install -g tslab
# or with pnpm
pnpm install -g tslab
# Install kernel specs
tslab install
# Verify kernels are available
jupyter kernelspec listYou should see tslab and jslab in the kernel list.
Configure with Claude Code
Add the server to Claude Code:
claude mcp add jupyter-kernel jupyter-kernel-mcpVerify the server is listed:
claude mcp list
Configure with other MCP clients
Add to your MCP client configuration (example for
mcp_config.json):{ "servers": { "jupyter-kernel": { "command": "jupyter-kernel-mcp" } } }
Run Jupyter Kernel MCP
The server starts automatically when called by your MCP client
No manual startup required - the server launches when your MCP client connects.
Start your first kernel:
In Claude Code or your MCP client:
Please start a new Jupyter kernel for data analysisExecute stateful code:
Load this dataset and show me the first few rows: import pandas as pd df = pd.read_csv('data.csv') df.head()Continue the analysis in follow-up messages:
Now group the data by category and calculate the mean valuesThe
dfvariable persists from the previous execution!
Available Tools
Tool | Description |
| Create a new Jupyter kernel for Python, TypeScript, or JavaScript |
| Execute code in any language kernel (auto-routes based on kernel type) |
| Show all active kernels with their languages |
| Display variables in a kernel's namespace |
| Get detailed kernel information |
| Stop and remove a specific kernel |
| Reset a kernel (clears all variables) |
Troubleshooting
Other troubleshooting resources:
Check server logs for detailed error messages
Verify your MCP client supports the required MCP protocol version
Ensure no firewall is blocking local kernel connections
Contributing guidelines
We welcome contributions! Please see our Contributing Guide for details on:
How to submit bug reports and feature requests
Development setup and testing procedures
Code style guidelines and review process
Additional documentation
For more information:
Model Context Protocol Specification - Official MCP documentation
Jupyter Client Documentation - Jupyter kernel communication protocol
Claude Code MCP Guide - Using MCP servers with Claude
How to get help
Need assistance? Here's how to get support:
GitHub Issues - Report bugs or request features
Email - Contact the maintainer at tom@codewithcheese.com
MCP Community - Join discussions in MCP community forums
Terms of use
Jupyter Kernel MCP is licensed under the MIT License.
Built with ❤️ for the AI agent development community
Available Tools
7 toolsexecute_codeA
Execute Python code in a persistent Jupyter kernel with maintained state.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | Python code to execute (variables persist between executions) | |
| kernel_id | Yes | ID of the kernel to execute code in (use list_kernels to see available kernels) | |
| timeout | No | Maximum execution time in seconds |
Output Schema
| Name | Required | Description |
|---|---|---|
| success | Yes | |
| output | Yes | |
| result | Yes | |
| error | Yes | |
| timestamp | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds the key behavioral trait of 'maintained state' beyond annotations, indicating that variables persist between executions. Annotations already indicate the tool is not read-only, and the description complements them well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence front-loading the core purpose without any wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of annotations and an output schema, the description is sufficiently complete. It captures the essential point of code execution with state persistence, though it omits potential side effects or error handling details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the description does not need to add parameter details. It provides no additional information beyond what is already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool executes Python code in a persistent kernel with maintained state, distinguishing it from sibling tools focused on kernel lifecycle management.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives; usage is implied by the context of sibling tools but not stated outright.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_kernel_statusARead-onlyIdempotent
Get detailed status information about a specific Jupyter kernel.
| Name | Required | Description | Default |
|---|---|---|---|
| kernel_id | Yes | ID of the kernel to check status for |
Output Schema
| Name | Required | Description |
|---|---|---|
| kernel_id | Yes | |
| status | Yes | |
| created_at | Yes | |
| language | Yes | |
| env_path | Yes | |
| details | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, covering the safety profile. The description adds 'detailed status' but does not elaborate on what status includes or any behavioral traits beyond the annotations. It is adequate but not enriched.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence that front-loads the action and resource. It is appropriately sized for the tool's simplicity, though a bit more detail could be added without harming conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (1 parameter, no enums), the presence of an output schema, and annotations covering read-only and idempotent behavior, the description provides sufficient context for an AI agent to understand the tool's purpose and use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the input schema fully describes the parameter. The tool description does not add any additional semantic value beyond what the schema provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and resource 'detailed status information about a specific Jupyter kernel'. It effectively distinguishes from siblings like list_kernels (listing all) and reset_kernel/stop_kernel (mutations). The slight vagueness of 'detailed status' prevents a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies its use for checking status of a single kernel, but does not explicitly state when to use it versus alternatives like list_kernels (for overview) or execute_code (for running code). No exclusions or additional guidance are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_kernelsARead-onlyIdempotent
List all currently active Jupyter kernels with their status information.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| success | Yes | |
| kernels | Yes | |
| count | Yes | |
| timestamp | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and idempotent behavior; the description adds that it returns status information, providing context beyond annotations without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, no redundancy, front-loaded with key action and result.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Description adequately covers the tool's purpose and output (active kernels with status). With an output schema present, return values need not be detailed. However, it could mention that it provides a snapshot of kernel health or resource usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, so the description cannot add parameter meaning; with 100% schema coverage, a baseline of 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists all active Jupyter kernels with status, distinguishing it from siblings like get_kernel_status which targets a single kernel.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives, but the context of sibling tools implies its use for listing all kernels rather than checking a specific one.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_variablesARead-onlyIdempotent
List all variables currently defined in the specified kernel's namespace.
| Name | Required | Description | Default |
|---|---|---|---|
| kernel_id | Yes | ID of the kernel to inspect variables from |
Output Schema
| Name | Required | Description |
|---|---|---|
| success | Yes | |
| variables | Yes | |
| count | Yes | |
| timestamp | Yes | |
| kernel_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, which cover safety and repeatability. The description adds no further behavioral details beyond the stated purpose, so it does not significantly enhance transparency beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single clear sentence with no unnecessary words, front-loaded with the action and resource. It is appropriately concise for the simplicity of the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has only one parameter, complete annotations, and an output schema, the description is sufficient. It covers the purpose, scope, and required input, leaving no critical gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the parameter description in the schema is already clear. The description adds the word 'namespace' but does not provide meaningful additional context or constraints beyond what the schema offers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'List', the resource 'variables', and the scope 'currently defined in the specified kernel's namespace'. It distinguishes from sibling tools that perform actions or retrieve status, leaving no ambiguity about the tool's function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when the agent needs to inspect variables in a kernel, but it does not explicitly state when to use this tool over alternatives, nor provide any when-not conditions. Given the distinct sibling tools, the lack of explicit guidance is acceptable but limits clarity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reset_kernelADestructiveIdempotent
Reset a Jupyter kernel by clearing all variables and state while keeping the same ID.
| Name | Required | Description | Default |
|---|---|---|---|
| kernel_id | Yes | ID of the kernel to reset (WARNING: This will clear all variables and state) |
Output Schema
| Name | Required | Description |
|---|---|---|
| kernel_id | Yes | |
| success | Yes | |
| message | Yes | |
| timestamp | Yes | |
| error | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true. Description adds that the kernel ID remains same, but doesn't explain side effects like aborting running code or impact on connected clients.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded with key information, no superfluous words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values are covered. However, for a destructive tool, additional context like 'kernels must be running' or 'state is lost permanently' would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema already describes kernel_id and includes a warning. Description adds no further meaning beyond what schema provides. Schema coverage is 100%.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (reset), the resource (Jupyter kernel), and the effect (clearing all variables and state while keeping ID). It distinguishes from sibling tools like start_kernel or stop_kernel.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool vs alternatives like restart_kernel or similar. No mention of prerequisites or scenarios where reset is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_kernelA
Start a new Jupyter kernel with persistent state for code execution.
| Name | Required | Description | Default |
|---|---|---|---|
| env_path | Yes | Full path to language runtime executable (e.g., /usr/bin/python3, /usr/bin/node) | |
| language | No | Programming language for the kernel (python, typescript, or javascript). Defaults to python for backward compatibility. | python |
| kernel_id | No | Custom kernel identifier (auto-generated if not provided) | |
| python_env | No | DEPRECATED: Use env_path instead. Full path to Python executable for backward compatibility. |
Output Schema
| Name | Required | Description |
|---|---|---|
| kernel_id | Yes | |
| success | Yes | |
| message | Yes | |
| timestamp | Yes | |
| error | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide that the tool is not read-only, not destructive, and not idempotent. The description adds 'persistent state', which is useful. However, it does not disclose potential side effects like memory consumption or the need to stop kernels.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, clear and to the point. No wasted words. Could be slightly improved by mentioning the return value explicitly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema, the description does not need to explain return values. It covers the core functionality, though it could mention that the kernel_id is returned or that the kernel must be started before code execution.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the description adds no additional meaning beyond what is already in the schema. The parameters are well-documented in the schema itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Start'), the resource ('new Jupyter kernel'), and a key characteristic ('persistent state for code execution'), which distinguishes it from siblings that execute code or manage kernels.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when or when not to use this tool. It implies usage when a kernel is needed for execution, but does not mention prerequisites (e.g., valid env_path) or conflicts (e.g., duplicate kernel_id).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
stop_kernelADestructiveIdempotent
Stop and permanently remove a Jupyter kernel and all its state.
| Name | Required | Description | Default |
|---|---|---|---|
| kernel_id | Yes | ID of the kernel to stop (WARNING: This will permanently remove the kernel and all its state) |
Output Schema
| Name | Required | Description |
|---|---|---|
| kernel_id | Yes | |
| success | Yes | |
| message | Yes | |
| timestamp | Yes | |
| error | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true. Description adds specificity: 'permanently remove all its state', clarifying scope of destruction. No other behavioral traits disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded with verb and object, zero unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple destructive tool with one param and output schema, description is sufficient. Could briefly mention irreversible nature beyond what annotations provide, but current is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Single parameter kernel_id is thoroughly described in input schema (including warning). Description provides no additional parameter context beyond what schema already offers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states exact action: stop and permanently remove a Jupyter kernel and all state. Sibling tool reset_kernel implies a non-permanent reset, so this tool's permanent removal is distinctive.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use vs. reset_kernel or start_kernel. The description implies permanence, but does not state conditions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
7 tool updates
v0.2.0- First observed
execute_code - First observed
get_kernel_status - First observed
list_kernels - First observed
list_variables - First observed
reset_kernel - First observed
start_kernel - First observed
stop_kernel
TDQS
Each tool targets a distinct operation: execution, kernel lifecycle, variable listing, and status. No overlapping functionality.
All tool names follow a consistent verb_noun pattern in lowercase snake_case, e.g., execute_code, reset_kernel.
7 tools is appropriate for managing Jupyter kernels: start, stop, reset, list, status, variable listing, and code execution. Not excessive or sparse.
Covers core kernel lifecycle and code execution. Missing features like interrupting a kernel or retrieving execution history, but essential operations are present.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
- mcp-serverOAuthai.cdbx
Build Apps and run code in 30 languages — sandboxed, with persistent sessions for agent loops.
Coding agents build full-stack apps in persistent workspaces and share them by link.
Hosted runtime for persistent agent teams, durable workflows, memory, schedules, and goals.
Build, validate, and deploy multi-agent AI solutions from any AI environment.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceProvides sandboxed code execution for AI agents with support for Python, JavaScript, and shell commands. Includes comprehensive safety features like destructive pattern blocking, timeout protection, and restricted file access for secure production use.22MIT
- AlicenseAqualityCmaintenanceEnables AI agents to create, read, edit, and execute Jupyter notebook cells, manage kernels, and connect to remote Jupyter servers.21MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to execute Jupyter notebook cells with persistent kernel state, output persistence, and structured JSON control surface.2-
- FlicenseAqualityDmaintenanceEnables AI assistants to securely execute Python and JavaScript code in sandboxed environments, with file management and package installation.788-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/codewithcheese/jupyter-kernel-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server