diff --git a/src/git/.python-version b/src/git/.python-version
index 2c073331..c8cfe395 100644
--- a/src/git/.python-version
+++ b/src/git/.python-version
@@ -1 +1 @@
-3.11
+3.10
diff --git a/src/git/README.md b/src/git/README.md
index cc8da29f..cb2681f7 100644
--- a/src/git/README.md
+++ b/src/git/README.md
@@ -1,9 +1,13 @@
-# mcp-git
+# mcp-git: A git MCP server
A Model Context Protocol server for Git repository interaction and automation. This server provides tools to read, search, and manipulate Git repositories via Large Language Models.
+Please note that mcp-git is currently in early development. The functionality and available tools are subject to change and expansion as we continue to develop and improve the server.
+
## Available Tools
+The current list of tools includes:
+
- `git_read_file`: Read contents of a file at a specific Git reference
- `git_list_files`: List all files in a repository or subdirectory
- `git_file_history`: Get commit history for a specific file
@@ -12,10 +16,15 @@ A Model Context Protocol server for Git repository interaction and automation. T
- `git_get_diff`: View diffs between Git references
- `git_get_repo_structure`: View repository file structure
- `git_list_repos`: List available Git repositories
+- `git_log`: Retrieve commit log for the repository
+- `git_list_branches`: List all branches in the repository
+- `git_list_tags`: List all tags in the repository
+
+This list is expected to grow as we add more functionality to the server. We welcome contributions from the community to expand and enhance the available tools.
## Installation
-### Using uv
+### Using uv (recommended)
When using [`uv`](https://docs.astral.sh/uv/) no specific installation is needed. We will
use [`uvx`](https://docs.astral.sh/uv/guides/tools/) to directly run *mcp-git*.
@@ -86,7 +95,9 @@ Alternatively, if using pip installation:
## Contributing
+We encourage contributions to help expand and improve mcp-git. Whether you want to add new tools, enhance existing functionality, or improve documentation, your input is valuable.
+
For examples of other MCP servers and implementation patterns, see:
https://github.com/modelcontextprotocol/servers
-Pull requests welcome!
+Pull requests are welcome! Feel free to contribute new ideas, bug fixes, or enhancements to make mcp-git even more powerful and useful.
diff --git a/src/git/pyproject.toml b/src/git/pyproject.toml
index 85af62fd..3fc2ae8c 100644
--- a/src/git/pyproject.toml
+++ b/src/git/pyproject.toml
@@ -1,9 +1,9 @@
[project]
name = "mcp-git"
-version = "0.1.0"
+version = "0.2.0"
description = "A Model Context Protocol server providing tools to read, search, and manipulate Git repositories programmatically via LLMs"
readme = "README.md"
-requires-python = ">=3.11"
+requires-python = ">=3.10"
authors = [{ name = "Anthropic, PBC." }]
maintainers = [{ name = "David Soria Parra", email = "davidsp@anthropic.com" }]
keywords = ["git", "mcp", "llm", "automation"]
@@ -13,7 +13,7 @@ classifiers = [
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.10",
]
dependencies = [
"click>=8.1.7",
@@ -30,5 +30,4 @@ requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.uv]
-index-strategy = "unsafe-best-match"
dev-dependencies = ["ruff>=0.7.3"]
diff --git a/src/git/src/mcp_git/__init__.py b/src/git/src/mcp_git/__init__.py
index 475404f9..25c85d50 100644
--- a/src/git/src/mcp_git/__init__.py
+++ b/src/git/src/mcp_git/__init__.py
@@ -1,4 +1,6 @@
import logging
+import json
+import sys
import click
import anyio
import anyio.lowlevel
@@ -7,8 +9,16 @@
from mcp.server import Server
from mcp.server.session import ServerSession
from mcp.server.stdio import stdio_server
-from mcp.types import TextContent, Tool, EmbeddedResource, ImageContent, ListRootsResult
-from enum import StrEnum
+from mcp.types import (
+ ClientCapabilities,
+ TextContent,
+ Tool,
+ EmbeddedResource,
+ ImageContent,
+ ListRootsResult,
+ RootsCapability,
+)
+from enum import Enum
import git
from git.objects import Blob, Tree
@@ -66,7 +76,21 @@ class ListReposInput(BaseModel):
pass
-class GitTools(StrEnum):
+class GitLogInput(BaseModel):
+ repo_path: str
+ max_count: int = 10
+ ref: str = "HEAD"
+
+
+class ListBranchesInput(BaseModel):
+ repo_path: str
+
+
+class ListTagsInput(BaseModel):
+ repo_path: str
+
+
+class GitTools(str, Enum):
READ_FILE = "git_read_file"
LIST_FILES = "git_list_files"
FILE_HISTORY = "git_file_history"
@@ -75,12 +99,19 @@ class GitTools(StrEnum):
GET_DIFF = "git_get_diff"
GET_REPO_STRUCTURE = "git_get_repo_structure"
LIST_REPOS = "git_list_repos"
+ GIT_LOG = "git_log"
+ LIST_BRANCHES = "git_list_branches"
+ LIST_TAGS = "git_list_tags"
def git_read_file(repo: git.Repo, file_path: str, ref: str = "HEAD") -> str:
tree = repo.commit(ref).tree
blob = tree / file_path
- return blob.data_stream.read().decode("utf-8", errors="replace")
+ try:
+ return blob.data_stream.read().decode("utf-8", errors="replace")
+ except UnicodeDecodeError:
+ # If it's a binary file, return a message indicating that
+ return "[Binary file content not shown]"
def git_list_files(repo: git.Repo, path: str = "", ref: str = "HEAD") -> Sequence[str]:
@@ -122,10 +153,14 @@ def git_search_code(
tree = repo.commit(ref).tree
for blob in tree.traverse():
if isinstance(blob, Blob) and Path(blob.path).match(file_pattern):
- content = blob.data_stream.read().decode("utf-8")
- for i, line in enumerate(content.splitlines()):
- if query in line:
- results.append(f"{blob.path}:{i+1}: {line}")
+ try:
+ content = blob.data_stream.read().decode("utf-8", errors="replace")
+ for i, line in enumerate(content.splitlines()):
+ if query in line:
+ results.append(f"{blob.path}:{i+1}: {line}")
+ except UnicodeDecodeError:
+ # Skip binary files
+ continue
return results
@@ -153,14 +188,35 @@ def build_tree(tree_obj: Tree) -> dict:
return str(structure)
+def git_log(repo: git.Repo, max_count: int = 10, ref: str = "HEAD") -> list[str]:
+ commits = list(repo.iter_commits(ref, max_count=max_count))
+ log = []
+ for commit in commits:
+ log.append(
+ f"Commit: {commit.hexsha}\n"
+ f"Author: {commit.author}\n"
+ f"Date: {commit.authored_datetime}\n"
+ f"Message: {commit.message}\n"
+ )
+ return log
+
+
+def git_list_branches(repo: git.Repo) -> list[str]:
+ return [str(branch) for branch in repo.branches]
+
+
+def git_list_tags(repo: git.Repo) -> list[str]:
+ return [str(tag) for tag in repo.tags]
+
+
async def serve(repository: Path | None) -> None:
# Set up logging
- logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
if repository is not None:
try:
git.Repo(repository)
+ logger.info(f"Using repository at {repository}")
except git.InvalidGitRepositoryError:
logger.error(f"{repository} is not a valid Git repository")
return
@@ -234,6 +290,28 @@ async def list_tools() -> list[Tool]:
"accessible to the current session.",
inputSchema=ListReposInput.schema(),
),
+ Tool(
+ name=GitTools.GIT_LOG,
+ description="Retrieves the commit log for the repository, showing the "
+ "history of commits including commit hashes, authors, dates, and "
+ "commit messages. This tool provides an overview of the project's "
+ "development history.",
+ inputSchema=GitLogInput.schema(),
+ ),
+ Tool(
+ name=GitTools.LIST_BRANCHES,
+ description="Lists all branches in the Git repository. This tool "
+ "provides an overview of the different lines of development in the "
+ "project.",
+ inputSchema=ListBranchesInput.schema(),
+ ),
+ Tool(
+ name=GitTools.LIST_TAGS,
+ description="Lists all tags in the Git repository. This tool "
+ "provides an overview of the tagged versions or releases in the "
+ "project.",
+ inputSchema=ListTagsInput.schema(),
+ ),
]
async def list_repos() -> Sequence[str]:
@@ -243,7 +321,14 @@ async def by_roots() -> Sequence[str]:
"server.request_context.session must be a ServerSession"
)
- roots_result: ListRootsResult = await server.request_context.session.list_roots()
+ if not server.request_context.session.check_client_capability(
+ ClientCapabilities(roots=RootsCapability())
+ ):
+ return []
+
+ roots_result: ListRootsResult = (
+ await server.request_context.session.list_roots()
+ )
logger.debug(f"Roots result: {roots_result}")
repo_paths = []
for root in roots_result.roots:
@@ -269,71 +354,123 @@ async def call_tool(
) -> list[TextContent | ImageContent | EmbeddedResource]:
if name == GitTools.LIST_REPOS:
result = await list_repos()
- return [TextContent(type="text", text=str(r)) for r in result]
+ logging.debug(f"repos={result}")
+ return [
+ TextContent(
+ type="text",
+ text=f"Here is some JSON that contains a list of git repositories: {json.dumps(result)}",
+ )
+ ]
repo_path = Path(arguments["repo_path"])
repo = git.Repo(repo_path)
match name:
case GitTools.READ_FILE:
+ content = git_read_file(
+ repo, arguments["file_path"], arguments.get("ref", "HEAD")
+ )
return [
TextContent(
type="text",
- text=git_read_file(
- repo, arguments["file_path"], arguments.get("ref", "HEAD")
- )
+ text=f"Here is some JSON that contains the contents of a file: {json.dumps({'content': content})}",
)
]
case GitTools.LIST_FILES:
+ files = git_list_files(
+ repo, arguments.get("path", ""), arguments.get("ref", "HEAD")
+ )
return [
- TextContent(type="text", text=str(f))
- for f in git_list_files(
- repo, arguments.get("path", ""), arguments.get("ref", "HEAD")
+ TextContent(
+ type="text",
+ text=f"Here is some JSON that contains a list of files: {json.dumps({'files': list(files)})}",
)
]
case GitTools.FILE_HISTORY:
+ history = git_file_history(
+ repo, arguments["file_path"], arguments.get("max_entries", 10)
+ )
return [
- TextContent(type="text", text=entry)
- for entry in git_file_history(
- repo, arguments["file_path"], arguments.get("max_entries", 10)
+ TextContent(
+ type="text",
+ text=f"Here is some JSON that contains a file's history: {json.dumps({'history': list(history)})}",
)
]
case GitTools.COMMIT:
result = git_commit(repo, arguments["message"], arguments.get("files"))
- return [TextContent(type="text", text=result)]
+ return [
+ TextContent(
+ type="text",
+ text=f"Here is some JSON that contains the commit result: {json.dumps({'result': result})}",
+ )
+ ]
case GitTools.SEARCH_CODE:
+ results = git_search_code(
+ repo,
+ arguments["query"],
+ arguments.get("file_pattern", "*"),
+ arguments.get("ref", "HEAD"),
+ )
return [
- TextContent(type="text", text=result)
- for result in git_search_code(
- repo,
- arguments["query"],
- arguments.get("file_pattern", "*"),
- arguments.get("ref", "HEAD"),
+ TextContent(
+ type="text",
+ text=f"Here is some JSON that contains code search matches: {json.dumps({'matches': results})}",
)
]
case GitTools.GET_DIFF:
+ diff = git_get_diff(
+ repo,
+ arguments["ref1"],
+ arguments["ref2"],
+ arguments.get("file_path"),
+ )
return [
TextContent(
type="text",
- text=git_get_diff(
- repo,
- arguments["ref1"],
- arguments["ref2"],
- arguments.get("file_path"),
- )
+ text=f"Here is some JSON that contains a diff: {json.dumps({'diff': diff})}",
)
]
case GitTools.GET_REPO_STRUCTURE:
+ structure = git_get_repo_structure(repo, arguments.get("ref", "HEAD"))
+ return [
+ TextContent(
+ type="text",
+ text=f"Here is some JSON that contains the repository structure: {json.dumps({'structure': structure})}",
+ )
+ ]
+
+ case GitTools.GIT_LOG:
+ log = git_log(
+ repo, arguments.get("max_count", 10), arguments.get("ref", "HEAD")
+ )
+ return [
+ TextContent(
+ type="text",
+ text=f"Here is some JSON that contains the git log: {json.dumps({'log': log})}",
+ )
+ ]
+
+ case GitTools.LIST_BRANCHES:
+ branches = git_list_branches(repo)
+ return [
+ TextContent(
+ type="text",
+ text=f"Here is some JSON that contains a list of branches: {json.dumps({'branches': branches})}",
+ )
+ ]
+
+ case GitTools.LIST_TAGS:
+ tags = git_list_tags(repo)
return [
TextContent(
type="text",
- text=git_get_repo_structure(repo, arguments.get("ref", "HEAD"))
+ text=f"Here is some JSON that contains a list of tags: {json.dumps({'tags': tags})}",
)
]
@@ -348,7 +485,14 @@ async def call_tool(
@click.command()
@click.option("-r", "--repository", type=click.Path(path_type=Path, dir_okay=True))
-def main(repository: Path | None):
+@click.option("-v", "--verbose", count=True)
+def main(repository: Path | None, verbose: int):
+ logging_level = logging.WARN
+ if verbose == 1:
+ logging_level = logging.INFO
+ elif verbose >= 2:
+ logging_level = logging.DEBUG
+ logging.basicConfig(level=logging_level, stream=sys.stderr)
anyio.run(serve, repository)
diff --git a/src/git/uv.lock b/src/git/uv.lock
index 456835c5..f994f688 100644
--- a/src/git/uv.lock
+++ b/src/git/uv.lock
@@ -1,5 +1,5 @@
version = 1
-requires-python = ">=3.11"
+requires-python = ">=3.10"
resolution-markers = [
"python_full_version < '3.13'",
"python_full_version >= '3.13'",
@@ -19,8 +19,10 @@ name = "anyio"
version = "4.6.2.post1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
+ { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
{ name = "idna" },
{ name = "sniffio" },
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9f/09/45b9b7a6d4e45c6bcb5bf61d19e3ab87df68e0601fa8c5293de3542546cc/anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c", size = 173422 }
wheels = [
@@ -57,6 +59,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
]
+[[package]]
+name = "exceptiongroup"
+version = "1.2.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 },
+]
+
[[package]]
name = "gitdb"
version = "4.0.11"
@@ -139,7 +150,7 @@ wheels = [
[[package]]
name = "mcp"
-version = "0.9.0"
+version = "0.9.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
@@ -149,14 +160,14 @@ dependencies = [
{ name = "sse-starlette" },
{ name = "starlette" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/cd/bb/fd56a5c331a6c95a4f2ec907683db3382d30b99b808ef6f46fa4f08a4b74/mcp-0.9.0.tar.gz", hash = "sha256:1d7e3f8d78bf5b37c98a233fce8cebbb86c57d8964d2c3b03cf08cdebd103d9a", size = 78343 }
+sdist = { url = "https://files.pythonhosted.org/packages/e7/1c/932818470ffd49c33509110c835101a8dc4c9cdd06028b9f647fb3dde237/mcp-0.9.1.tar.gz", hash = "sha256:e8509a37c2ab546095788ed170e0fb4d7ce0cf5a3ee56b6449c78af27321a425", size = 78218 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/6f/07/077116e6a23dd0546391f5caa81b4f52938d8a81f2449c55c0b50c0215bf/mcp-0.9.0-py3-none-any.whl", hash = "sha256:e09aca08eadaf0552541aaa71271b44f99a6a5d16e5b1b03c421366f72b51753", size = 31691 },
+ { url = "https://files.pythonhosted.org/packages/b3/a0/2ee813d456b57a726d583868417d1ad900fbe12ee3c8cd866e3e804ca486/mcp-0.9.1-py3-none-any.whl", hash = "sha256:7f640fcfb0be486aa510594df309920ae1d375cdca1f8aff21db3a96d837f303", size = 31562 },
]
[[package]]
name = "mcp-git"
-version = "0.1.0"
+version = "0.2.0"
source = { editable = "." }
dependencies = [
{ name = "click" },
@@ -204,6 +215,18 @@ dependencies = [
]
sdist = { url = "https://files.pythonhosted.org/packages/e2/aa/6b6a9b9f8537b872f552ddd46dd3da230367754b6f707b8e1e963f515ea3/pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863", size = 402156 }
wheels = [
+ { url = "https://files.pythonhosted.org/packages/5c/8b/d3ae387f66277bd8104096d6ec0a145f4baa2966ebb2cad746c0920c9526/pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b", size = 1867835 },
+ { url = "https://files.pythonhosted.org/packages/46/76/f68272e4c3a7df8777798282c5e47d508274917f29992d84e1898f8908c7/pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166", size = 1776689 },
+ { url = "https://files.pythonhosted.org/packages/cc/69/5f945b4416f42ea3f3bc9d2aaec66c76084a6ff4ff27555bf9415ab43189/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb", size = 1800748 },
+ { url = "https://files.pythonhosted.org/packages/50/ab/891a7b0054bcc297fb02d44d05c50e68154e31788f2d9d41d0b72c89fdf7/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916", size = 1806469 },
+ { url = "https://files.pythonhosted.org/packages/31/7c/6e3fa122075d78f277a8431c4c608f061881b76c2b7faca01d317ee39b5d/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07", size = 2002246 },
+ { url = "https://files.pythonhosted.org/packages/ad/6f/22d5692b7ab63fc4acbc74de6ff61d185804a83160adba5e6cc6068e1128/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232", size = 2659404 },
+ { url = "https://files.pythonhosted.org/packages/11/ac/1e647dc1121c028b691028fa61a4e7477e6aeb5132628fde41dd34c1671f/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2", size = 2053940 },
+ { url = "https://files.pythonhosted.org/packages/91/75/984740c17f12c3ce18b5a2fcc4bdceb785cce7df1511a4ce89bca17c7e2d/pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f", size = 1921437 },
+ { url = "https://files.pythonhosted.org/packages/a0/74/13c5f606b64d93f0721e7768cd3e8b2102164866c207b8cd6f90bb15d24f/pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3", size = 1966129 },
+ { url = "https://files.pythonhosted.org/packages/18/03/9c4aa5919457c7b57a016c1ab513b1a926ed9b2bb7915bf8e506bf65c34b/pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071", size = 2110908 },
+ { url = "https://files.pythonhosted.org/packages/92/2c/053d33f029c5dc65e5cf44ff03ceeefb7cce908f8f3cca9265e7f9b540c8/pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119", size = 1735278 },
+ { url = "https://files.pythonhosted.org/packages/de/81/7dfe464eca78d76d31dd661b04b5f2036ec72ea8848dd87ab7375e185c23/pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f", size = 1917453 },
{ url = "https://files.pythonhosted.org/packages/5d/30/890a583cd3f2be27ecf32b479d5d615710bb926d92da03e3f7838ff3e58b/pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8", size = 1865160 },
{ url = "https://files.pythonhosted.org/packages/1d/9a/b634442e1253bc6889c87afe8bb59447f106ee042140bd57680b3b113ec7/pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d", size = 1776777 },
{ url = "https://files.pythonhosted.org/packages/75/9a/7816295124a6b08c24c96f9ce73085032d8bcbaf7e5a781cd41aa910c891/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e", size = 1799244 },
@@ -240,6 +263,14 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/16/16/b805c74b35607d24d37103007f899abc4880923b04929547ae68d478b7f4/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f", size = 2116814 },
{ url = "https://files.pythonhosted.org/packages/d1/58/5305e723d9fcdf1c5a655e6a4cc2a07128bf644ff4b1d98daf7a9dbf57da/pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769", size = 1738360 },
{ url = "https://files.pythonhosted.org/packages/a5/ae/e14b0ff8b3f48e02394d8acd911376b7b66e164535687ef7dc24ea03072f/pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5", size = 1919411 },
+ { url = "https://files.pythonhosted.org/packages/13/a9/5d582eb3204464284611f636b55c0a7410d748ff338756323cb1ce721b96/pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5", size = 1857135 },
+ { url = "https://files.pythonhosted.org/packages/2c/57/faf36290933fe16717f97829eabfb1868182ac495f99cf0eda9f59687c9d/pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec", size = 1740583 },
+ { url = "https://files.pythonhosted.org/packages/91/7c/d99e3513dc191c4fec363aef1bf4c8af9125d8fa53af7cb97e8babef4e40/pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480", size = 1793637 },
+ { url = "https://files.pythonhosted.org/packages/29/18/812222b6d18c2d13eebbb0f7cdc170a408d9ced65794fdb86147c77e1982/pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068", size = 1941963 },
+ { url = "https://files.pythonhosted.org/packages/0f/36/c1f3642ac3f05e6bb4aec3ffc399fa3f84895d259cf5f0ce3054b7735c29/pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801", size = 1915332 },
+ { url = "https://files.pythonhosted.org/packages/f7/ca/9c0854829311fb446020ebb540ee22509731abad886d2859c855dd29b904/pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728", size = 1957926 },
+ { url = "https://files.pythonhosted.org/packages/c0/1c/7836b67c42d0cd4441fcd9fafbf6a027ad4b79b6559f80cf11f89fd83648/pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433", size = 2100342 },
+ { url = "https://files.pythonhosted.org/packages/a9/f9/b6bcaf874f410564a78908739c80861a171788ef4d4f76f5009656672dfe/pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753", size = 1920344 },
]
[[package]]
@@ -327,6 +358,7 @@ source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "h11" },
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e0/fc/1d785078eefd6945f3e5bab5c076e4230698046231eb0f3747bc5c8fa992/uvicorn-0.32.0.tar.gz", hash = "sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e", size = 77564 }
wheels = [
diff --git a/src/sqlite/src/sqlite/__init__.py b/src/sqlite/src/sqlite/__init__.py
index 6217b1fe..8fc09807 100644
--- a/src/sqlite/src/sqlite/__init__.py
+++ b/src/sqlite/src/sqlite/__init__.py
@@ -1,9 +1,11 @@
from . import server
import asyncio
+
def main():
"""Main entry point for the package."""
asyncio.run(server.main())
+
# Optionally expose other important items at package level
-__all__ = ['main', 'server']
\ No newline at end of file
+__all__ = ["main", "server"]
diff --git a/src/sqlite/src/sqlite/server.py b/src/sqlite/src/sqlite/server.py
index 3d36b495..ab7b6eed 100644
--- a/src/sqlite/src/sqlite/server.py
+++ b/src/sqlite/src/sqlite/server.py
@@ -28,7 +28,7 @@ def _init_database(self):
if cursor.fetchone()[0] == 0:
cursor.execute(
"INSERT INTO notes (name, content) VALUES (?, ?)",
- ("example", "This is an example note.")
+ ("example", "This is an example note."),
)
conn.commit()
@@ -55,13 +55,13 @@ def _add_note(self, name: str, content: str):
with closing(conn.cursor()) as cursor:
cursor.execute(
"INSERT OR REPLACE INTO notes (name, content) VALUES (?, ?)",
- (name, content)
+ (name, content),
)
conn.commit()
def __init__(self):
super().__init__("sqlite")
-
+
# Initialize SQLite database
self.db_path = "notes.db"
self._init_database()
@@ -118,10 +118,14 @@ async def handle_get_prompt(
"""Generate a prompt using notes from the database"""
if name != "summarize-notes":
raise ValueError(f"Unknown prompt: {name}")
- notes = "\n" + "\n".join(
- f"\n{content}\n"
- for name, content in self._get_notes().items()
- ) + "\n"
+ notes = (
+ "\n"
+ + "\n".join(
+ f"\n{content}\n"
+ for name, content in self._get_notes().items()
+ )
+ + "\n"
+ )
style = (arguments or {}).get("style", "simple")
prompt = """
Your task is to provide a summary of the notes provided below.
@@ -207,4 +211,4 @@ async def main():
experimental_capabilities={},
),
),
- )
\ No newline at end of file
+ )