Kotlin MCP server for JetBrains Space code reviews and merge requests.
- Java 21
- Access to a JetBrains Space instance such as
https://jetbrains.team - A Space access token for the recommended env-based local auth flow, or a Space OAuth application for
space_authorize
- OAuth authorization code flow with PKCE against
https://jetbrains.team - Stored credentials with refresh-token support
- Listing visible Space projects
- Listing project reviews with public HTTP API filters:
repositorystatetypetextauthorreviewerfromto
- Aggregating "my reviews" across visible projects by scanning projects with
author=meandreviewer=me - Fetching a review with:
- resolved review author / creator details when available
- branch information
- commits
- optionally changed files
- review feed messages
- flattened human-authored comments
- code discussion threads and replies
- Listing changed files in a review or merge request with normalized:
- repository
- path / old path
- revision
- diff size
- conflict / read metadata when available
- Listing human-authored review comments with optional author filtering
- Posting a plain review comment to the main review feed
- Creating a code discussion anchored to a file/line
- Replying to an existing discussion channel
-
Get the runnable fat jar in one of these ways:
-
Download it from GitHub Releases.
-
Or build it from source:
./gradlew build
buildincludes tests and ktlint checks.
In both cases, the file you want is the fat jar:
build/libs/space-mcp-server-0.2.0-all.jar -
-
Configure your MCP host to run that jar with
java -jar:{ "mcpServers": { "Space": { "command": "java", "args": [ "-jar", "/path/to/space-mcp-server/build/libs/space-mcp-server-0.2.0-all.jar" ], "env": { "SPACE_SERVER_URL": "https://jetbrains.team", "SPACE_ACCESS_TOKEN": "your-token" } } } }If
javais not Java 21 on your machine, use the absolute path to a Java 21 binary instead. -
Authenticate:
- Recommended: set
SPACE_SERVER_URLandSPACE_ACCESS_TOKENin the MCP host config for local non-interactive auth. - Alternative: call
space_authorizeonce to complete OAuth.
- Recommended: set
-
Verify the integration with:
space_auth_statusspace_list_my_reviewsspace_get_reviewspace_list_review_changesspace_list_review_comments
./gradlew buildThe runnable fat jar is created at:
build/libs/space-mcp-server-0.2.0-all.jar
CIruns on every pull request and on pushes tomasterandmain.- The CI job runs
./gradlew build, which includes compilation, tests, and ktlint checks. - Every CI run uploads:
- the runnable fat jar artifact
- Gradle reports and test results
Releaseruns on pushed tags matchingv*and can also be started manually with a tag input from the Actions UI.- Release runs build the server, publish a versioned fat jar plus
SHA256SUMS.txtas workflow artifacts, and attach those files to the GitHub release.
If you downloaded the release jar, run that file. If you built from source, run the jar from build/libs.
java -jar build/libs/space-mcp-server-0.2.0-all.jarThe server uses stdio transport.
The server supports two auth modes:
- direct bearer-token bootstrap via environment variables for local
stdioclients - OAuth via the
space_authorizeMCP tool
This is the default and recommended authorization flow for local MCP clients.
Set these environment variables in the MCP host configuration:
SPACE_ACCESS_TOKENSPACE_SERVER_URLfor your Space organization URL, for examplehttps://jetbrains.team- optional
SPACE_SCOPE - optional
SPACE_CLIENT_ID
SPACE_ACCESS_TOKEN also overrides the stored access token at runtime when OAuth credentials already exist.
Example local MCP config:
{
"mcpServers": {
"Space": {
"command": "java",
"args": [
"-jar",
"/path/to/space-mcp-server/build/libs/space-mcp-server-0.2.0-all.jar"
],
"env": {
"SPACE_SERVER_URL": "https://jetbrains.team",
"SPACE_ACCESS_TOKEN": "your-token"
}
}
}
}When you use OAuth, stored credentials are written to:
$XDG_CONFIG_HOME/space-mcp-server/credentials.json, or~/.config/space-mcp-server/credentials.json
OAuth is available as a secondary flow when you do not want to pass a Space access token directly through the MCP host configuration.
Use the space_authorize MCP tool with:
clientId- optional
clientSecret - optional
serverUrl(defaults tohttps://jetbrains.team) - optional
scope(defaults to**) - optional
redirectUri
Default redirect URI:
http://localhost:63363/api/space/oauth/authorization_code
For a normal Space application, configure the exact same redirect URI in the Space app settings.
Check the current auth state:
{ "name": "space_auth_status", "arguments": {} }Example response:
{
"configured": true,
"authenticated": true,
"serverUrl": "https://jetbrains.team",
"currentUser": {
"id": "hero-001",
"username": "Leia.Organa"
}
}List your reviews:
{
"name": "space_list_my_reviews",
"arguments": {
"projectKey": "ALDERAAN",
"role": "both",
"limit": 20
}
}Example response:
{
"reviews": [
{
"projectKey": "ALDERAAN",
"matchedRoles": ["reviewer"],
"review": {
"number": 1138,
"title": "[falcon] Tune hyperdrive ignition timing",
"resolvedAuthor": {
"username": "Han.Solo"
}
}
}
],
"scannedProjects": 20,
"projectScanTruncated": true,
"requestedLimit": 20
}Fetch a review with commits and comments:
{
"name": "space_get_review",
"arguments": {
"projectKey": "ALDERAAN",
"review": "number:1138",
"includeCommits": true,
"includeChanges": true,
"includeComments": true
}
}Example response excerpt:
{
"review": {
"number": 1138,
"title": "[falcon] Tune hyperdrive ignition timing",
"resolvedAuthor": {
"username": "Han.Solo"
}
},
"commits": [
{
"repositoryInReview": {
"name": "millennium-falcon"
},
"commits": [
{
"id": "cafebabedeadbeef00112233445566778899aabb",
"author": {
"name": "Han Solo"
}
}
]
}
],
"changes": {
"scope": "merge-request-files",
"changes": [
{
"repository": "millennium-falcon",
"path": "src/Hyperdrive.kt",
"changeType": "MODIFIED",
"revision": "source-head-sha"
}
]
},
"comments": {
"entries": [
{
"kind": "code-discussion",
"text": "Please rename this",
"author": {
"name": "Leia.Organa"
}
}
]
}
}List changed files in a review:
{
"name": "space_list_review_changes",
"arguments": {
"projectKey": "ALDERAAN",
"review": "number:1138",
"limit": 100
}
}Example response:
{
"review": {
"number": 1138,
"title": "[falcon] Tune hyperdrive ignition timing"
},
"scope": "merge-request-files",
"count": 1,
"changes": [
{
"kind": "merge-request-file",
"repository": "millennium-falcon",
"path": "src/Hyperdrive.kt",
"oldPath": "src/NavComputer.kt",
"revision": "source-head-sha",
"changeType": "RENAMED",
"diffSize": {
"added": 12,
"deleted": 4
}
}
]
}Filter review comments by author:
{
"name": "space_list_review_comments",
"arguments": {
"projectKey": "ALDERAAN",
"review": "number:1138",
"author": "Leia.Organa"
}
}Example response:
{
"authorFilter": "Leia.Organa",
"count": 2,
"comments": [
{
"kind": "review-feed",
"text": "Looks good"
},
{
"kind": "code-discussion",
"anchor": {
"filename": "src/Hyperdrive.kt",
"line": 42
}
}
]
}There is no dedicated logout tool.
To reset locally stored OAuth credentials, delete:
$XDG_CONFIG_HOME/space-mcp-server/credentials.json, or~/.config/space-mcp-server/credentials.json
Environment-based auth can be reset by removing SPACE_ACCESS_TOKEN from the MCP host configuration.
space_auth_statusspace_authorizespace_list_projectsspace_list_reviewsspace_list_my_reviewsspace_get_reviewspace_list_review_changesspace_list_review_commentsspace_post_review_commentspace_create_code_discussionspace_reply_to_discussion
Verified from local Space sources and SDK references:
- Public review listing endpoint exists:
GET /projects/{project}/code-reviews - Public review details endpoint exists:
GET /projects/{project}/code-reviews/{reviewId} - Public review details-with-commits endpoint exists:
GET /projects/{project}/code-reviews/{reviewId}/details - Public review-file endpoints exist:
GET /projects/{project}/code-reviews/{reviewId}/merge-filesGET /projects/{project}/code-reviews/{reviewId}/files
- Review comments are accessible through the review
feedChannelIdplus chat APIs - Public code discussion creation endpoint exists:
POST /projects/{project}/code-reviews/code-discussions - Public chat message endpoints exist for discussion replies and main review-feed comments
- A direct public "list my review participations" endpoint exists in source, but it is behind an internal HTTP API feature flag. This server does not depend on it.
- A public
submitPendingMessages(reviewId)HTTP endpoint was not confirmed. The server can create pending messages/discussions, but reliable publication of pending drafts is not implemented. - Cross-project "my reviews" is implemented by scanning visible projects and using public
authorandreviewerfilters, not by a single dedicated public endpoint.
This repository is licensed under Apache-2.0. See LICENSE.
For publication and reference-repository audit notes, see PROVENANCE.md.