Skip to content

Conversation

@msanatan
Copy link
Contributor

@msanatan msanatan commented Dec 19, 2025

We're now on pypi! It's another way to run the server: https://pypi.org/project/mcpforunityserver/

@dsarno @Scriptwonder I originally thought about adding this to get past the uvx issues with Claude Desktop on Windows before David's fix. Hopefully users will appreciate an alternative all the same!

Summary by CodeRabbit

  • Chores
    • Added MIT License to the project
    • Updated project metadata including authors, keywords, and classifier information
    • Configured automated package publishing to PyPI
    • Set minimum Python version requirement to 3.10
    • Declared package dependencies

✏️ Tip: You can customize this high-level summary in your review settings.

@msanatan msanatan self-assigned this Dec 19, 2025
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Dec 19, 2025

Reviewer's Guide

Prepares the Python server package for distribution via PyPI by standardizing the package name/metadata, wiring telemetry to the new package identity, and adding a CI workflow to build and publish distributions to PyPI and TestPyPI.

File-Level Changes

Change Details Files
Standardize Python package metadata for PyPI distribution.
  • Lowercase the project name to align with PyPI naming conventions
  • Add license, authors, classifiers, and keywords to the project metadata
  • Declare repository and issue tracker URLs in the project URLs section
Server/pyproject.toml
Align telemetry package identification with the new PyPI package name.
  • Update PACKAGE_NAME constant to the new, lowercase project name
  • Adjust error message to reference the new package name consistently
Server/src/core/telemetry.py
Introduce CI workflow to build and publish the package to PyPI and TestPyPI.
  • Add GitHub Actions workflow that builds distributions using uv in the Server directory
  • Upload built distributions as artifacts in a dedicated build job
  • Publish artifacts to PyPI on tagged commits using trusted publishing
  • Publish artifacts to TestPyPI on every push using the same built distributions
.github/workflows/publish-pypi.yml
Add project license file for distribution compliance.
  • Include a LICENSE file under the Server directory to match the declared MIT license
Server/LICENSE

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 19, 2025

Walkthrough

Introduces a GitHub Actions workflow to automate Python package publishing to PyPI and TestPyPI. Adds package metadata, MIT license file, and updates package configuration in pyproject.toml. Standardizes package name from "MCPForUnityServer" to "mcpforunityserver" across build configuration and telemetry constants.

Changes

Cohort / File(s) Summary
PyPI Publishing Workflow
.github/workflows/publish-pypi.yml
New GitHub Actions workflow that builds Python distribution (wheel and tarball) from Server directory, uploads artifacts, and provides conditional publishing paths: one for PyPI on tag pushes and another for TestPyPI on all pushes.
Package Licensing & Metadata
Server/LICENSE
Server/pyproject.toml
Adds MIT License file and updates pyproject.toml with package metadata (authors, classifiers, keywords), license declaration, Python version requirement (≥3.10), expanded dependencies (fastmcp, mcp, pydantic, tomli, fastapi, uvicorn), project URLs, and renames package display name to "mcpforunityserver".
Telemetry Package Name Alignment
Server/src/core/telemetry.py
Updates PACKAGE_NAME constant and error message text from "MCPForUnityServer" to "mcpforunityserver" for consistency with new package naming.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Server/pyproject.toml requires verification that all new dependency versions are compatible and that package metadata is accurate
  • .github/workflows/publish-pypi.yml should be reviewed to confirm PyPI credentials/environment setup is correct

Possibly related PRs

Poem

🐰 A package now stands tall and lean,
With MIT's shield and pipelines clean,
From Server's root to PyPI's gate,
Our names aligned, our build's first-rate!
hops excitedly 📦✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Publish to pypi' directly reflects the main objective of the pull request, which introduces PyPI publishing automation and publishes the package to PyPI.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • The GitHub Actions workflow is configured with on: push, which will build and upload artifacts on every branch push; consider narrowing this to push to main and/or tags to avoid unnecessary CI load.
  • The Programming Language :: Python :: 3.14 classifier in pyproject.toml may be premature; you might want to drop it until 3.14 is released and actually tested to avoid overstating compatibility.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The GitHub Actions workflow is configured with `on: push`, which will build and upload artifacts on every branch push; consider narrowing this to `push` to main and/or tags to avoid unnecessary CI load.
- The `Programming Language :: Python :: 3.14` classifier in `pyproject.toml` may be premature; you might want to drop it until 3.14 is released and actually tested to avoid overstating compatibility.

## Individual Comments

### Comment 1
<location> `.github/workflows/publish-pypi.yml:26-30` </location>
<code_context>
+      - name: Build a binary wheel and a source tarball
+        run: uv build
+
+      - name: Store the distribution packages
+        uses: actions/upload-artifact@v6
+        with:
+          name: python-package-distributions
+          path: Server/dist/
+
+  publish-to-pypi:
</code_context>

<issue_to_address>
**issue (bug_risk):** Artifact upload/download paths likely produce an extra nested directory, which will break `gh-action-pypi-publish` defaults.

`upload-artifact` preserves the `Server/dist/` directory, but the publish jobs download into `dist/` and rely on the default `packages-dir: dist/`. This will likely place wheels under `dist/Server/dist/...`, so `gh-action-pypi-publish` won’t see them.

To fix this, either:
- upload with `path: Server/dist/*`, or
- download into `Server/dist/` and set `packages-dir: Server/dist/` in the publish steps.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +26 to +30
- name: Store the distribution packages
uses: actions/upload-artifact@v6
with:
name: python-package-distributions
path: Server/dist/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Artifact upload/download paths likely produce an extra nested directory, which will break gh-action-pypi-publish defaults.

upload-artifact preserves the Server/dist/ directory, but the publish jobs download into dist/ and rely on the default packages-dir: dist/. This will likely place wheels under dist/Server/dist/..., so gh-action-pypi-publish won’t see them.

To fix this, either:

  • upload with path: Server/dist/*, or
  • download into Server/dist/ and set packages-dir: Server/dist/ in the publish steps.

@dsarno
Copy link
Collaborator

dsarno commented Dec 19, 2025

@msanatan exciting! Good thinking!

readme = "README.md"
license = "MIT"
authors = [
{name = "Marcus Sanatan", email = "msanatan@gmail.com"},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dsarno @Scriptwonder is it OK to list you all as authors here?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
Server/src/core/telemetry.py (1)

63-63: Consider shortening the error message.

The static analysis tool suggests avoiding long messages directly in the exception. You could shorten this to just the essential information or define a custom exception class.

🔎 Optional refactor to address static analysis hint
-    raise FileNotFoundError("pyproject.toml not found for mcpforunityserver")
+    raise FileNotFoundError(f"pyproject.toml not found for {PACKAGE_NAME}")

This approach uses the constant and keeps the message concise.

.github/workflows/publish-pypi.yml (1)

54-76: Consider limiting TestPyPI publishing frequency.

The publish-to-testpypi job runs on every push without any conditional filters. This could lead to:

  • Excessive TestPyPI uploads (potentially hitting rate limits)
  • Version conflicts if the version in pyproject.toml doesn't change between pushes
  • Cluttered TestPyPI with many development versions

Consider adding a condition to limit when this runs, such as:

  • Only on pushes to specific branches (e.g., main or develop)
  • Only on pull request merges
  • Or remove it entirely if manual testing on TestPyPI is sufficient
🔎 Example: Limit TestPyPI publishing to main branch
  publish-to-testpypi:
    name: Publish Python 🐍 distribution 📦 to TestPyPI
+   if: github.ref == 'refs/heads/main'
    needs:
      - build

Or limit to non-tag pushes to avoid duplicate publishes:

  publish-to-testpypi:
    name: Publish Python 🐍 distribution 📦 to TestPyPI
+   if: "!startsWith(github.ref, 'refs/tags/')"
    needs:
      - build
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between df3a493 and 85ab994.

📒 Files selected for processing (4)
  • .github/workflows/publish-pypi.yml (1 hunks)
  • Server/LICENSE (1 hunks)
  • Server/pyproject.toml (2 hunks)
  • Server/src/core/telemetry.py (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: JohanHoltby
Repo: CoplayDev/unity-mcp PR: 309
File: MCPForUnity/Editor/Helpers/ServerInstaller.cs:478-508
Timestamp: 2025-10-13T13:41:00.086Z
Learning: In the MCPForUnityTools feature (MCPForUnity/Editor/Helpers/ServerInstaller.cs), the design intentionally forces users to have only one .py file per MCPForUnityTools folder to keep file tracking simple. Package-style tools (subdirectories with __init__.py) are not supported.
📚 Learning: 2025-10-13T13:41:00.086Z
Learnt from: JohanHoltby
Repo: CoplayDev/unity-mcp PR: 309
File: MCPForUnity/Editor/Helpers/ServerInstaller.cs:478-508
Timestamp: 2025-10-13T13:41:00.086Z
Learning: In the MCPForUnityTools feature (MCPForUnity/Editor/Helpers/ServerInstaller.cs), the design intentionally forces users to have only one .py file per MCPForUnityTools folder to keep file tracking simple. Package-style tools (subdirectories with __init__.py) are not supported.

Applied to files:

  • Server/src/core/telemetry.py
  • Server/pyproject.toml
📚 Learning: 2025-11-05T18:23:12.349Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 368
File: MCPForUnity/UnityMcpServer~/src/resources/menu_items.py:15-15
Timestamp: 2025-11-05T18:23:12.349Z
Learning: In Unity MCP, the `name` parameter in the `mcp_for_unity_resource` decorator is the external API name exposed to MCP clients (LLMs, AI agents). The command string passed to `async_send_command_with_retry` or `async_send_with_unity_instance` (e.g., "get_menu_items") is the internal command identifier that must match the C# side. These are decoupled, allowing external API naming to evolve independently of internal command routing.

Applied to files:

  • Server/pyproject.toml
📚 Learning: 2025-10-03T22:11:46.002Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 301
File: docs/CUSTOM_TOOLS.md:54-62
Timestamp: 2025-10-03T22:11:46.002Z
Learning: In Unity MCP, the `description` parameter in the `mcp_for_unity_tool` decorator is technically optional but should always be included as a best practice. Without it, there's a higher chance that MCP clients will not parse the tool correctly. All Unity MCP tools should include the description in the decorator for compatibility.

Applied to files:

  • Server/pyproject.toml
🪛 Ruff (0.14.8)
Server/src/core/telemetry.py

63-63: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review
🔇 Additional comments (8)
Server/LICENSE (1)

1-21: LGTM!

The MIT License is properly formatted with the correct copyright year and holder.

Server/src/core/telemetry.py (1)

37-37: LGTM! Package name follows Python conventions.

The package name change to all lowercase follows PEP 8 naming conventions for Python packages.

Server/pyproject.toml (4)

2-2: LGTM! Package name standardization.

The package name change to lowercase follows Python packaging conventions and is consistent with the telemetry module updates.


6-11: LGTM! Proper package metadata.

The license declaration and authors section are well-formatted and align with the new LICENSE file.


29-29: LGTM! Useful package metadata.

The keywords and project URLs are relevant and will help users discover and contribute to the project.

Also applies to: 47-49


12-28: Remove or update the concern about Python 3.14.

Python 3.14 was released on 7 October 2025, so including it in the classifiers is appropriate. The classifier on line 22 is valid and does not require changes.

.github/workflows/publish-pypi.yml (2)

32-53: LGTM! Proper PyPI publishing configuration.

The conditional if: startsWith(github.ref, 'refs/tags/') ensures that releases to PyPI only happen on tagged versions, which is the correct practice. The use of trusted publishing (OIDC) is also a security best practice.


6-31: LGTM! Well-structured build job.

The build job correctly sets the working directory, uses modern tooling (uv), and uploads artifacts for downstream jobs. The cache dependency glob correctly references the existing Server/uv.lock file.

@msanatan msanatan merged commit 12e1b62 into CoplayDev:main Dec 19, 2025
2 checks passed
@msanatan msanatan deleted the publish-to-pypi branch December 19, 2025 20:43
@coderabbitai coderabbitai bot mentioned this pull request Dec 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants