mcp-kg-skills
Manages a knowledge graph in Neo4j, allowing creation, retrieval, update, and deletion of nodes (scripts, skills, knowledge, environment variables) and relationships (CONTAINS, RELATE_TO), as well as executing Python scripts with automatic dependency management and secret protection.
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., "@mcp-kg-skillsfind all Python functions for file I/O"
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.
MCP Knowledge Graph Skills
A Model Context Protocol (MCP) server that manages a graph of reusable Python functions, documentation, and environment variables. Claude can dynamically compose and execute scripts by importing functions from the graph.
Features
Graph-Based Knowledge Management: Organize skills, scripts, documentation, and environments in a Neo4j knowledge graph
Dynamic Script Composition: Import and combine Python functions at execution time
Automatic Dependency Management: PEP 723 inline script metadata with uv-powered execution
Secret Protection: Automatic detection and sanitization of sensitive environment variables
Relationship Tracking: Connect related skills and resources with CONTAINS and RELATE_TO relationships
Flexible Querying: Explore the knowledge graph using read-only Cypher queries
Related MCP server: RAG MCP Server
Quick Start
Get started in 3 steps:
# 1. Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 2. Start Neo4j (using Docker)
docker run -d --name neo4j -p 7687:7687 -e NEO4J_AUTH=neo4j/password neo4j:latest
# 3. Create config file
mkdir -p ~/.mcp-kg-skills/config
cat > ~/.mcp-kg-skills/config/database.yaml << 'EOF'
database:
uri: "bolt://localhost:7687"
username: "neo4j"
password: "password"
database: "neo4j"
execution:
cache_dir: "~/.mcp-kg-skills/cache"
env_dir: "~/.mcp-kg-skills/envs"
default_timeout: 300
max_timeout: 600
security:
secret_patterns:
- "^SECRET_"
- "_SECRET$"
- "^.*_KEY$"
- "^.*_PASSWORD$"
- "^.*_TOKEN$"
logging:
level: "INFO"
EOF
# 4. Run the server
uvx mcp-kg-skillsThat's it! Now configure your MCP client (see MCP Client Configuration).
Architecture
┌─────────────────────────────────────────────────────┐
│ LLM (Claude via MCP Client) │
└─────────────────┬───────────────────────────────────┘
│ MCP Protocol (FastMCP 2.10)
┌─────────────────▼───────────────────────────────────┐
│ MCP Server (mcp-kg-skills) │
│ ┌───────────────────────────────────────────────┐ │
│ │ Tools: nodes, relationships, env, │ │
│ │ execute, query │ │
│ └────────────────┬──────────────────────────────┘ │
│ ┌────────────────▼──────────────────────────────┐ │
│ │ Script Executor + Secret Protection │ │
│ │ (uv run + PEP 723) │ │
│ └────────────────┬──────────────────────────────┘ │
│ ┌────────────────▼──────────────────────────────┐ │
│ │ Neo4j Database Interface │ │
│ └────────────────┬──────────────────────────────┘ │
└───────────────────┼───────────────────────────────┘
│
┌───────────────────▼───────────────────────────────┐
│ Neo4j Graph Database │
│ Nodes: SKILL, KNOWLEDGE, SCRIPT, ENV │
│ Relationships: CONTAINS, RELATE_TO │
└───────────────────────────────────────────────────┘Installation
Prerequisites
Python 3.12 or higher
uv - Fast Python package installer
Neo4j 4.4+, 5.x, or 2025.x
MCP-compatible client (e.g., Claude Desktop)
Install uv
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"Install MCP Knowledge Graph Skills
Option 1: From PyPI (Recommended)
# Install directly from PyPI
pip install mcp-kg-skills
# Or using uv
uv pip install mcp-kg-skills
# Or run with uvx (no installation needed)
uvx mcp-kg-skillsOption 2: From Source (Development)
# Clone the repository
git clone https://github.com/fmktech/mcp-kg-skills.git
cd mcp-kg-skills
# Install with uv
uv pip install -e .Install Neo4j
Option 1: Docker (Recommended)
docker run -d \
--name neo4j \
-p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/your-password \
neo4j:latestOption 2: Neo4j Desktop
Download from neo4j.com/download
Option 3: Neo4j Aura (Cloud)
Sign up at console.neo4j.io
Configuration
1. Create Configuration File
Create the config directory and file:
# Create config directory
mkdir -p ~/.mcp-kg-skills/config
# Create configuration file
cat > ~/.mcp-kg-skills/config/database.yaml << 'EOF'
database:
uri: "bolt://localhost:7687"
username: "neo4j"
password: "${NEO4J_PASSWORD}" # Or set directly: "your-password"
database: "neo4j"
execution:
cache_dir: "~/.mcp-kg-skills/cache"
env_dir: "~/.mcp-kg-skills/envs"
default_timeout: 300
max_timeout: 600
security:
secret_patterns:
- "^SECRET_"
- "_SECRET$"
- "^.*_KEY$"
- "^.*_PASSWORD$"
- "^.*_TOKEN$"
logging:
level: "INFO"
EOFIf you cloned the repository, you can copy the example:
cp .mcp-kg-skills/config/database.yaml.example \
~/.mcp-kg-skills/config/database.yaml2. Configure Neo4j Connection
Edit ~/.mcp-kg-skills/config/database.yaml and update:
uri: Your Neo4j connection URI (e.g.,bolt://localhost:7687or Neo4j Aura URI)username: Your Neo4j username (default:neo4j)password: Your Neo4j password (or use environment variable${NEO4J_PASSWORD})database: Database name (default:neo4j)
3. Set Environment Variables (Optional)
If using environment variables for passwords:
# Set Neo4j password
export NEO4J_PASSWORD="your-password"
# Add to your shell profile (~/.bashrc, ~/.zshrc, etc.)
echo 'export NEO4J_PASSWORD="your-password"' >> ~/.zshrcMCP Client Configuration
Claude Desktop
Add to your Claude Desktop config file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
Option 1: Using uvx (Recommended - No Installation Required)
{
"mcpServers": {
"mcp-kg-skills": {
"command": "uvx",
"args": ["mcp-kg-skills"],
"env": {
"NEO4J_PASSWORD": "your-password"
}
}
}
}Option 2: Using pip-installed package
{
"mcpServers": {
"mcp-kg-skills": {
"command": "mcp-kg-skills",
"env": {
"NEO4J_PASSWORD": "your-password"
}
}
}
}Option 3: Using uv with local development installation
{
"mcpServers": {
"mcp-kg-skills": {
"command": "uv",
"args": [
"--directory",
"/path/to/mcp-kg-skills",
"run",
"mcp-kg-skills"
],
"env": {
"NEO4J_PASSWORD": "your-password"
}
}
}
}Note: Replace /path/to/mcp-kg-skills with the actual path to your cloned repository.
Usage
Node Types
SKILL - High-level organizational unit
{
"name": "data-pipeline",
"description": "ETL pipeline for data processing",
"body": "# Data Pipeline\n\nMarkdown content..."
}KNOWLEDGE - Documentation and context
{
"name": "api-documentation",
"description": "REST API documentation",
"body": "# API Docs\n\nMarkdown content..."
}SCRIPT - Python functions with PEP 723 dependencies
{
"name": "fetch_data",
"description": "Fetch data from API",
"function_signature": "fetch_data(url: str) -> dict",
"body": """
# /// script
# requires-python = ">=3.12"
# dependencies = ["requests>=2.31.0"]
# ///
import requests
def fetch_data(url: str) -> dict:
response = requests.get(url)
response.raise_for_status()
return response.json()
"""
}ENV - Environment variable collections
{
"name": "production",
"description": "Production environment variables",
"variables": {
"DATABASE_HOST": "prod.db.example.com",
"DATABASE_PORT": "5432",
"DATABASE_PASSWORD": "secret123" # Auto-detected as secret
}
}MCP Tools
1. nodes - Manage nodes
Create a SKILL:
nodes(
operation="create",
node_type="SKILL",
data={
"name": "data-pipeline",
"description": "ETL data processing pipeline",
"body": "# Data Pipeline\n\nThis skill manages ETL processes..."
}
)Create a SCRIPT:
nodes(
operation="create",
node_type="SCRIPT",
data={
"name": "fetch_data",
"description": "Fetch JSON data from URL",
"function_signature": "fetch_data(url: str) -> dict",
"body": """
# /// script
# requires-python = ">=3.12"
# dependencies = ["requests>=2.31.0"]
# ///
import requests
def fetch_data(url: str) -> dict:
response = requests.get(url)
return response.json()
"""
}
)List nodes:
nodes(
operation="list",
node_type="SCRIPT",
filters={"name": "fetch", "limit": 10}
)Read a node:
nodes(
operation="read",
node_type="SCRIPT",
node_id="script-123"
)Update a node:
nodes(
operation="update",
node_type="SCRIPT",
node_id="script-123",
data={"description": "Updated description"}
)Delete a node:
nodes(
operation="delete",
node_type="SCRIPT",
node_id="script-123"
)2. relationships - Manage relationships
Create CONTAINS relationship:
relationships(
operation="create",
relationship_type="CONTAINS",
source_id="skill-123",
target_id="script-456"
)Create RELATE_TO relationship:
relationships(
operation="create",
relationship_type="RELATE_TO",
source_id="skill-123",
target_id="skill-789",
properties={"reason": "related functionality"}
)List relationships:
relationships(
operation="list",
source_id="skill-123"
)Delete relationship:
relationships(
operation="delete",
rel_id="rel-123"
)3. env - Manage environment variables
Create environment:
env(
operation="create",
name="production",
description="Production environment",
variables={
"DATABASE_HOST": "prod.db.example.com",
"DATABASE_PASSWORD": "secret123", # Auto-detected as secret
"API_KEY": "abc123xyz" # Auto-detected as secret
}
)Read environment (secrets masked):
env(
operation="read",
env_id="env-123"
)
# Returns: {"DATABASE_HOST": "prod.db.example.com", "DATABASE_PASSWORD": "<SECRET>", ...}Update environment:
env(
operation="update",
env_id="env-123",
variables={"NEW_VAR": "value"}
)List variable keys only:
env(
operation="list_keys",
env_id="env-123"
)4. execute - Execute Python code
Execute with imported scripts:
execute(
code="""
# Imported functions are available by name
data = fetch_data("https://api.example.com/users")
processed = process_users(data)
print(f"Processed {len(processed)} users")
""",
imports=["fetch_data", "process_users"],
timeout=60
)Execute standalone code:
execute(
code="print('Hello, World!')",
timeout=10
)5. query - Query the graph
Find scripts in a skill:
query(
cypher="""
MATCH (s:SKILL {name: $skill_name})-[:CONTAINS]->(script:SCRIPT)
RETURN script.name, script.function_signature
""",
parameters={"skill_name": "data-pipeline"}
)Find skills using an environment:
query(
cypher="""
MATCH (script:SCRIPT)-[:CONTAINS]->(env:ENV {name: $env_name})
MATCH (skill:SKILL)-[:CONTAINS]->(script)
RETURN DISTINCT skill.name, skill.description
""",
parameters={"env_name": "production"}
)Explore related skills:
query(
cypher="""
MATCH (s1:SKILL)-[:RELATE_TO]-(s2:SKILL)
WHERE s1.name = $name
RETURN s2.name, s2.description
""",
parameters={"name": "etl-pipeline"}
)Example Workflow
1. Create a Skill
# Create skill
nodes(
operation="create",
node_type="SKILL",
data={
"name": "web-scraper",
"description": "Web scraping utilities",
"body": "# Web Scraper\n\nUtilities for web scraping..."
}
)
# Returns: {"success": true, "node": {"id": "skill-abc123", ...}}2. Create Scripts
# Fetch HTML
nodes(
operation="create",
node_type="SCRIPT",
data={
"name": "fetch_html",
"description": "Fetch HTML from URL",
"function_signature": "fetch_html(url: str) -> str",
"body": """
# /// script
# requires-python = ">=3.12"
# dependencies = ["requests>=2.31.0"]
# ///
import requests
def fetch_html(url: str) -> str:
return requests.get(url).text
"""
}
)
# Returns: {"success": true, "node": {"id": "script-def456", ...}}
# Parse HTML
nodes(
operation="create",
node_type="SCRIPT",
data={
"name": "parse_html",
"description": "Extract data from HTML",
"function_signature": "parse_html(html: str) -> dict",
"body": """
# /// script
# requires-python = ">=3.12"
# dependencies = ["beautifulsoup4>=4.12.0"]
# ///
from bs4 import BeautifulSoup
def parse_html(html: str) -> dict:
soup = BeautifulSoup(html, 'html.parser')
return {
'title': soup.title.string if soup.title else None,
'links': [a['href'] for a in soup.find_all('a', href=True)]
}
"""
}
)
# Returns: {"success": true, "node": {"id": "script-ghi789", ...}}3. Create Environment
env(
operation="create",
name="scraper-config",
description="Web scraper configuration",
variables={
"USER_AGENT": "MyBot/1.0",
"RATE_LIMIT": "10",
"API_KEY": "secret-key-123" # Auto-detected as secret
}
)
# Returns: {"success": true, "node": {"id": "env-jkl012", ...}}4. Link Everything Together
# Skill CONTAINS scripts
relationships(
operation="create",
relationship_type="CONTAINS",
source_id="skill-abc123",
target_id="script-def456"
)
relationships(
operation="create",
relationship_type="CONTAINS",
source_id="skill-abc123",
target_id="script-ghi789"
)
# Scripts CONTAIN environment
relationships(
operation="create",
relationship_type="CONTAINS",
source_id="script-def456",
target_id="env-jkl012"
)5. Execute Combined Scripts
execute(
code="""
# Both functions are available
html = fetch_html("https://example.com")
data = parse_html(html)
print(f"Page title: {data['title']}")
print(f"Found {len(data['links'])} links")
""",
imports=["fetch_html", "parse_html"],
timeout=30
)
# Dependencies (requests, beautifulsoup4) are automatically installed
# Environment variables from scraper-config are available
# Secrets are sanitized from outputSecurity Features
Automatic Secret Detection
Environment variables matching these patterns are automatically detected as secrets:
SECRET_**_SECRET*_KEY*_PASSWORD*_TOKEN*_API_KEY*_PRIVATE_KEY
Secret Protection
Storage: Secrets are stored in
~/.mcp-kg-skills/envs/*.envfiles (outside project directory)API Responses: Secret values are replaced with
<SECRET>Execution Output: Secret values are replaced with
<REDACTED>File Permissions:
.envfiles are created with0600permissions
Testing
Quick Start
# Setup development environment
./dev.sh setup
# Start test services
./dev.sh start
# Run all tests
./dev.sh test
# Run with coverage
./dev.sh test-covTest Structure
tests/
├── conftest.py # Shared fixtures
├── unit/ # Unit tests (no external dependencies)
│ ├── test_security.py
│ ├── test_dependency_parser.py
│ └── test_models.py
└── integration/ # Integration tests (SQLite by default, Neo4j optional)
├── test_database.py
└── test_end_to_end.pyDatabase Backends for Testing
Integration tests support two database backends:
SQLite (default): Fast in-memory testing, no setup required
Neo4j (optional): Full graph database testing with Cypher queries
# Run integration tests with SQLite (default - fast, no setup)
pytest tests/integration/
# Run integration tests with Neo4j
export TEST_DB=neo4j
export NEO4J_URI="bolt://localhost:7688"
export NEO4J_PASSWORD="testpassword"
pytest tests/integration/Running Tests
# All tests (unit + integration with SQLite)
pytest
# Unit tests only
pytest tests/unit/
# Integration tests with SQLite (default)
pytest tests/integration/
# Integration tests with Neo4j
TEST_DB=neo4j NEO4J_URI=bolt://localhost:7688 NEO4J_PASSWORD=testpassword pytest tests/integration/
# Specific test file
pytest tests/unit/test_security.py -v
# Specific test
pytest tests/unit/test_security.py::TestSecretDetector::test_default_patterns -v
# With coverage
pytest --cov=mcp_kg_skills --cov-report=htmlUsing the dev.sh Script
# Run all tests
./dev.sh test
# Run specific tests
./dev.sh test tests/unit/
# Run with coverage report
./dev.sh test-cov
# Format code before committing
./dev.sh format
# Run linter
./dev.sh lint
# Type check
./dev.sh typecheckUsing Make
# Run tests
make test
# Unit tests only
make test-unit
# Integration tests only
make test-integration
# With coverage
make test-cov
# Code quality checks
make lint format typecheckWriting Tests
Use pytest fixtures:
import pytest
@pytest.mark.asyncio
async def test_create_node(clean_db, sample_skill_data):
"""Test creating a node."""
node = await clean_db.create_node("SKILL", sample_skill_data)
assert node["id"] is not NoneSee CONTRIBUTING.md for detailed testing guidelines.
Development
Project Structure
mcp-kg-skills/
├── src/mcp_kg_skills/
│ ├── __init__.py
│ ├── server.py # FastMCP server
│ ├── models.py # Pydantic models
│ ├── config.py # Configuration
│ ├── exceptions.py # Custom exceptions
│ ├── database/
│ │ ├── abstract.py # Database interface
│ │ └── neo4j.py # Neo4j implementation
│ ├── execution/
│ │ ├── dependency.py # PEP 723 parser
│ │ └── runner.py # Script executor
│ ├── security/
│ │ └── secrets.py # Secret detection
│ ├── tools/
│ │ ├── nodes.py # Node CRUD
│ │ ├── relationships.py
│ │ ├── env.py
│ │ ├── execute.py
│ │ └── query.py
│ └── utils/
│ └── env_file.py # ENV file manager
├── tests/
├── pyproject.toml
└── README.mdRunning Tests
# Install dev dependencies
uv pip install -e ".[dev]"
# Run tests
pytest
# With coverage
pytest --cov=mcp_kg_skills --cov-report=htmlCode Quality
# Format code
ruff format .
# Lint code
ruff check .
# Type checking
mypy src/Troubleshooting
Neo4j Connection Issues
# Check Neo4j is running
docker ps | grep neo4j
# Check Neo4j logs
docker logs neo4j
# Test connection
neo4j-admin connectivity testuv Not Found
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Verify installation
uv --versionPermission Errors
# Fix directory permissions
chmod 700 ~/.mcp-kg-skills/envs/
chmod 600 ~/.mcp-kg-skills/envs/*.envLicense
MIT
Contributing
Contributions are welcome! Please:
Fork the repository
Create a feature branch
Make your changes
Add tests
Submit a pull request
Support
Issues: GitHub Issues
Discussions: GitHub Discussions
Available Tools
5 toolsenvA
Manage environment variables with automatic secret detection.
Variables matching SECRET_*, *_KEY, *_PASSWORD, *_TOKEN patterns are automatically detected and hidden from LLM responses. ENV files are stored at .mcp-kg-skills/envs/{env_id}.env
| Name | Required | Description | Default |
|---|---|---|---|
| keys | No | Variable keys to retrieve (for list_keys) - can be list or JSON string | |
| name | No | ENV name (for create) | |
| env_id | No | ENV node ID | |
| operation | Yes | Operation to perform (create, read, update, delete, list_keys) | |
| variables | No | Environment variables - can be dict or JSON string | |
| description | No | ENV description |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosing behavior. It reveals that variables matching secret patterns are automatically hidden from LLM responses and that files are stored at a specific path. These are meaningful behavioral details that a user would need to know, though it does not mention side effects like deletion permanence.
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 three short paragraphs, front-loaded with the core purpose. Every sentence provides useful information: the main function, secret detection behavior, and storage location. There is no redundant phrasing or filler.
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?
The tool has an output schema, so return values are already covered. The description supplies important context about secret handling and file storage. It does not address error cases or operation-specific effects, but for a tool of this complexity (6 params, 5 operations) it is reasonably complete.
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?
All parameters are described in the schema (100% coverage), so the baseline is 3. The description adds little direct parameter context, but it does explain the secret detection patterns that relate to variable keys. However, it does not elaborate on operation-specific parameter usage beyond what the schema provides.
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 states the tool 'Manage environment variables', clearly identifying the resource and function. It distinguishes from sibling tools (nodes, relationships, execute, query) by focusing on environment variables. However, 'manage' is somewhat generic and does not enumerate the specific CRUD operations, though the schema's operation parameter clarifies this.
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 does not provide any guidance on when to use this tool versus alternatives. There is no mention of context, prerequisites, or exclusions. The description only states what it does, not when it should be preferred over other tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
executeA
Execute Python code with dynamically imported functions from SCRIPT nodes.
The system automatically:
Loads specified SCRIPT nodes
Merges their PEP 723 dependencies
Loads ENV variables from connected nodes AND directly specified envs
Executes code using 'uv run'
Sanitizes output to remove secret values
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | Python code to execute | |
| envs | No | List of ENV node names to load directly - can be list or JSON string (in addition to ENVs connected to imported scripts via CONTAINS) | |
| imports | No | List of SCRIPT node names to import - can be list or JSON string | |
| timeout | No | Execution timeout in seconds (max 600) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries full responsibility. It discloses several behavioral traits: automatic loading of SCRIPT nodes, merging PEP 723 dependencies, loading ENV variables, executing via 'uv run', and sanitizing output to remove secrets. This gives a good sense of what happens during execution, though it doesn't address side effects or security boundaries.
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 compact with a clear main line and bullet-pointed automatic behaviors. Every sentence adds value, no redundancy.
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?
The tool is a code executor with multiple automatic steps. The description covers the key aspects of loading, dependency merging, env handling, execution method, and output sanitization. With an output schema present, the lack of return-value detail is acceptable. However, it could mention error behavior or access to imported names for added 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 covers 100% of parameters, so baseline is 3. The description adds meaning by explaining that 'imports' are SCRIPT nodes with PEP 723 dependency merging, and that 'envs' are directly specified ENV nodes in addition to connected ones, enriching the schema's brief parameter descriptions.
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 identifies the tool as executing Python code and importing functions from SCRIPT nodes, using a specific verb ('Execute') and resource, distinguishing it from sibling tools like 'query' or 'env'.
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 provides clear context for using this tool (when you need to run Python code with SCRIPT node imports), though it doesn't explicitly state when to avoid it or mention alternatives. This fits 'clear context, no exclusions'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nodesA
Manage graph nodes (SKILL, KNOWLEDGE, SCRIPT, ENV).
Supports create, read, update, delete, and list operations.
Args:
operation: Operation to perform (create, read, update, delete, list)
node_type: Type of node (SKILL, KNOWLEDGE, SCRIPT, ENV)
node_id: Node ID (for read, update, delete)
data: Node data (for create, update) - can be dict or JSON string
filters: Filter criteria (for list) - can be dict or JSON string
Returns:
Operation result
SCRIPT Node Best Practices:
- Do NOT include `if __name__ == '__main__':` blocks - they are
automatically stripped during execution to prevent unintended side effects
- Export functions/classes that should be callable from user code
- Keep example/test code in separate functions, not in __main__ blocks
- Use PEP 723 metadata for dependencies
- To use environment variables, create an ENV node and connect it to the
SCRIPT using a CONTAINS relationship: SCRIPT -[:CONTAINS]-> ENV
The ENV variables will be automatically loaded during execution
Examples:
Create a SKILL node:
```
nodes(
operation="create",
node_type="SKILL",
data={
"name": "data-pipeline",
"description": "ETL pipeline for data processing",
"body": "# Data Pipeline\n\nThis skill..."
}
)
```
Create a SCRIPT node (note: no __main__ block):
```
nodes(
operation="create",
node_type="SCRIPT",
data={
"name": "fetch_data",
"description": "Fetch data from API",
"function_signature": "fetch_data(url: str) -> dict",
"body": '''# /// script
requires-python = ">=3.12"
dependencies = ["requests>=2.31.0"]
///
import requests
def fetch_data(url: str) -> dict: response = requests.get(url) response.raise_for_status() return response.json() ''' } ) ```
List SCRIPT nodes:
```
nodes(
operation="list",
node_type="SCRIPT",
filters={"name": "fetch"}
)
```| Name | Required | Description | Default |
|---|---|---|---|
| data | No | ||
| filters | No | ||
| node_id | No | ||
| node_type | Yes | ||
| operation | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It discloses important behaviors: __main__ blocks are automatically stripped from SCRIPT nodes, ENV variables are auto-loaded via CONTAINS relationships, and data parameters accept dicts or JSON strings. These specifics go beyond a generic CRUD description, though it does not cover all edge behaviors (e.g., update merge/replace semantics).
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 well-structured with clear sections (overview, args, returns, best practices, examples) and front-loaded purpose. Although lengthy, the SCRIPT best practices and examples add significant value and avoid redundancy, earning their place.
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 5 parameters and complex SCRIPT-node handling, the description is nearly complete. It includes all parameter semantics, best practices, and examples for create and list. Since an output schema exists, the vague 'Returns: Operation result' is acceptable, but missing examples for read/update/delete and potential update semantics are minor 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 0%, so the description must compensate—and it does thoroughly. It explains each parameter's purpose, enumerates allowed values for operation and node_type, specifies which parameters apply to which operations, and clarifies that data/filters can be dicts or JSON strings.
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 opens with 'Manage graph nodes' and explicitly lists the node types (SKILL, KNOWLEDGE, SCRIPT, ENV) and supported operations (create, read, update, delete, list). This makes the tool's purpose unmistakable and distinct from siblings like 'relationships' or 'env'.
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 provides rich operational details (Args, SCRIPT best practices, examples) but never explicitly states when to choose this tool over alternatives. The usage context is implied by the tool name and node-type scope, but there is no direct when/when-not guidance or mention of sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
queryA
Execute read-only Cypher queries to explore the knowledge graph.
Only MATCH, RETURN, WITH, WHERE, ORDER BY operations are allowed. Results are automatically sanitized to hide secret values.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results (max 1000) | |
| cypher | Yes | Read-only Cypher query | |
| parameters | No | Query parameters - can be dict or JSON string |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the read-only nature, the exact set of allowed operations, and a key safety feature: 'Results are automatically sanitized to hide secret values.' This goes beyond the schema and gives critical behavioral context, though it does not address error handling, pagination, or rate limits.
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 two concise sentences: the first states the purpose, the second lists constraints. Every sentence adds value, and it is front-loaded with the core action. No waste or redundancy.
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?
The description is quite complete given the rich schema (full parameter coverage), an output schema (handles return values), and its own behavioral notes. It covers the essential safety and constraint aspects, but could have explicitly mentioned that this is a graph exploration tool versus node/relationship access, though that is implied by 'knowledge graph' and sibling context.
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?
The schema already covers all parameters with 100% description coverage, so the baseline is 3. The description adds a little extra meaning to the 'cypher' parameter by enumerating allowed operations, but it does not explain other parameters (limit, parameters) beyond what the schema already says.
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's function: 'Execute read-only Cypher queries to explore the knowledge graph.' It uses a specific verb (execute), a resource (Cypher queries), and a domain (knowledge graph), while the read-only qualifier distinguishes it from sibling 'execute' or 'nodes' tools.
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?
It provides clear context for when to use the tool (to explore the knowledge graph through Cypher) and explicitly restricts allowed operations ('Only MATCH, RETURN, WITH, WHERE, ORDER BY operations are allowed'), which helps the agent avoid invalid or write queries. However, it does not mention any alternatives or exclusions relative to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
relationshipsB
Manage relationships between nodes (CONTAINS, RELATE_TO).
Supports create, delete, and list operations. Prevents circular CONTAINS dependencies.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results (for list) | |
| offset | No | Offset for pagination (for list) | |
| rel_id | No | Relationship ID (for delete) | |
| operation | Yes | Operation to perform (create, delete, list) | |
| source_id | No | Source node ID | |
| target_id | No | Target node ID | |
| properties | No | Relationship properties - can be dict or JSON string | |
| relationship_type | No | Type of relationship (CONTAINS, RELATE_TO) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so description must carry full burden. It only discloses that circular CONTAINS dependencies are prevented, but doesn't explain side effects of delete/create, permission requirements, or error behavior.
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?
Three concise sentences with no filler. Front-loaded purpose, then supported operations, then key behavioral safeguard.
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. But the description doesn't clarify conditional parameter usage based on operation, despite the schema providing some hints. Could be improved with examples or when-to-use conditions.
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 description doesn't need to add much. It does mention relationship types which align with relationship_type parameter, but adds no operational nuance beyond 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?
Description clearly states the tool manages relationships between nodes with specific relationship types (CONTAINS, RELATE_TO) and enumerates operations (create, delete, list). This distinguishes it from sibling tools like nodes or query.
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. It does not mention exclusions, prerequisites, or alternative tools for similar operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a clearly distinct responsibility: nodes manages node CRUD, relationships manages edges, env handles environment variables, execute runs scripts, and query performs read-only graph queries. No overlap in purposes.
All tool names are single lowercase words—nodes, relationships, env, execute, query. While some are nouns and some are verbs, the naming convention is perfectly uniform and predictable.
Five tools is an ideal count for this domain. Each tool covers a essential aspect of the knowledge graph skill management workflow, and none feel redundant or missing.
The tool set provides full CRUD for nodes, create/delete/list for relationships, env management, script execution, and graph querying. This is a complete lifecycle covering all obvious operations for the server's purpose.
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
End-to-end agent-managed company brain. Docs, diagrams, plans, Knowledge Graph. Lean & affordable.
Shared memory for coding agents. Stop re-explaining your codebase every session.
Manage portable AI agent playbooks, Agent Skills, MCP configurations, personas, and memory.
Company brain for AI agents — temporal knowledge graph search, exploration, and durable memory.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables storage and retrieval of knowledge in a graph database format, allowing users to create, update, search, and delete entities and relationships in a Neo4j-powered knowledge graph through natural language.5
- FlicenseCqualityDmaintenanceCombines a knowledge graph with RAG (Retrieval-Augmented Generation) capabilities for semantic code indexing and search. Enables creating entity relationships, managing observations, and performing semantic searches across indexed codebases.13
- FlicenseNot gradedqualityCmaintenanceTransforms code repositories and development documentation into a queryable Neo4j knowledge graph, enabling AI assistants to perform intelligent code analysis, dependency mapping, impact assessment, and automated documentation generation across 15+ programming languages.7
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Neo4j graph databases through natural language, supporting Cypher queries, schema management, data manipulation, and graph algorithms.MIT
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/fkesheh/mcp-kg-skills'
If you have feedback or need assistance with the MCP directory API, please join our Discord server