Skip to content

Add OCI Speech MCP Server - #426

Open
Prabhutva wants to merge 2 commits into
oracle:mainfrom
Prabhutva:main
Open

Prabhutva wants to merge 2 commits into
oracle:mainfrom
Prabhutva:main

Conversation

@Prabhutva

Copy link
Copy Markdown
Member

Description

Adds the initial release of the OCI Speech MCP Server (v1.0.0), a locally run stdio MCP server that enables agents and MCP clients to use OCI Speech through the OCI Python SDK.

Transcription Jobs

Adds the following tools:

  • create_transcription_job
  • get_transcription_job
  • list_transcription_jobs
  • update_transcription_job
  • delete_transcription_job
  • cancel_transcription_job
  • change_transcription_job_compartment
  • list_transcription_tasks
  • get_transcription_task
  • cancel_transcription_task
  • download_transcription_results
  • transcribe_local_file

The transcribe_local_file tool provides an end-to-end local transcription workflow. It validates and uploads a local media file to OCI Object Storage, creates and optionally monitors the transcription job, and downloads successful JSON and SRT outputs to a restricted local directory.

Transcription features include diarization, configurable speaker counts, punctuation, profanity filtering, multiple transcription models and domains, Whisper prompting, and SRT output.

Resources and prompts provide guidance for:

  • Creating and managing transcription jobs and tasks
  • Transcribing local audio files
  • Choosing whether to enable diarization
  • Troubleshooting unsuccessful jobs
  • Safely handling local files and downloaded results

Customizations

Adds the following tools:

  • create_customization
  • get_customization
  • list_customizations
  • update_customization
  • delete_customization
  • change_customization_compartment

Customization inputs support inline entities, pronunciations, reference examples, Object Storage datasets, and reusable entity customizations.

The accompanying resource and prompt explain how to select, structure, create, train, update, and reuse OCI Speech customizations.

Text to Speech

Adds the following tools:

  • list_voices
  • synthesize_speech

Speech synthesis supports plain text and SSML, configurable voices, audio formats, sample rates, and safe local output handling.

The TTS and SSML resources include examples and guidance for:

  • Selecting an appropriate voice
  • Adding pauses, emphasis, and pronunciation hints
  • Controlling speaking rate, pitch, and volume
  • Reading dates, numbers, telephone numbers, and characters
  • Validating SSML before synthesis
  • Helping an agent transform plain text into customized SSML

Extras

Adds the following tool:

  • setup_transcription_notifications

This tool creates or reuses an OCI Notifications topic and creates OCI Events rules for transcription job completion and failure events. Subscription creation remains an explicit user action so confirmation endpoints are not configured without consent.

Additional resources and prompts cover:

  • OCI Speech prerequisites
  • Required IAM policies
  • Service limits
  • OCI Events and Notifications
  • Troubleshooting
  • OCI Realtime Speech integration
  • Live transcription using the OCI AI Speech Realtime Python SDK

Realtime transcription guidance keeps the persistent WebSocket connection in the user's application, where audio capture and playback occur, instead of holding a long-running connection inside the stdio MCP server.

Motivation and context

This server makes OCI Speech workflows directly accessible to MCP-compatible agents while continuing to use the user's existing OCI credentials and authorization policies.

It reduces the setup required for workflows involving Object Storage, transcription result retrieval, diarization, customizations, SSML generation, speech synthesis, and transcription job notifications.

The implementation separates tools, prompts, and resources by capability so future OCI Speech modules can be added without expanding the server entry point.

The server also provides:

  • Authentication through oracle-mcp-common
  • A package-derived oci-speech-mcp/1.0.0 OCI SDK user agent
  • Bounded pagination
  • Sanitized OCI error responses
  • Restricted local input and output paths
  • Protection against credential and sensitive-file access

Dependencies and prerequisites

Runtime dependencies include:

  • Python 3.13
  • fastmcp==3.4.5
  • oci==2.182.1
  • oracle-mcp-common>=0.1.0,<0.2.0
  • pydantic>=2.13.4,<3

Users require a configured OCI authentication profile and the appropriate OCI Speech, Object Storage, Events, Notifications, and IAM permissions for the operations they intend to use.

Type of change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

The server was validated with:

make test project=oci-speech-mcp-server
make lint

Automated validation results:

  • 45 unit tests passed
  • 97.21% code coverage, exceeding the required 90% threshold
  • Repository lint checks passed
  • All supported OCI authentication paths apply the expected oci-speech-mcp/1.0.0 user agent

Live stdio MCP validation confirmed discovery of all 21 tools, 11 resources, and 9 prompts. Every resource was read and every prompt was rendered.

Transcription Jobs

  • Uploaded and transcribed a local audio file
  • Monitored the transcription job through completion
  • Downloaded JSON and SRT results
  • Tested job creation, retrieval, listing, update, compartment change, and deletion
  • Tested transcription task listing and retrieval
  • Exercised job and task cancellation requests

Customizations

  • Created and trained a customization
  • Retrieved and listed customizations
  • Updated and deleted a customization
  • Validated supported customization dataset mappings

Text to Speech

  • Listed available voices
  • Synthesized speech from plain text
  • Synthesized speech from SSML
  • Validated local output handling and SSML input validation

Extras

  • Created an OCI Notifications topic
  • Created OCI Events rules for transcription job completion and failure
  • Validated the prerequisite, IAM policy, service-limit, notification, and realtime guidance

To reproduce the live tests:

  1. Configure a valid OCI profile.
  2. Ensure the profile has access to OCI Speech and a test compartment.
  3. Configure the MCP server as documented in its README.
  4. Connect through an MCP client using stdio.
  5. Exercise the transcription, customization, TTS, and notification tools.

Test Configuration:

  • Hardware: Apple Silicon Mac
  • Toolchain: Python 3.13.12, uv 0.10.0, pytest 9.1.1, repository lint tooling
  • SDK: OCI Python SDK 2.182.1, FastMCP 3.4.5
  • OCI region: us-phoenix-1
  • Authentication: OCI CLI-compatible session-token profile

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my feature works
  • New and existing applicable unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules (N/A: no dependent changes are required)

@oracle-contributor-agreement oracle-contributor-agreement Bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Aug 27, 2026

@dustin-sale dustin-sale left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review by @dustin-sale via Codex.

Requested changes

  • src/oci-speech-mcp-server/oracle/oci_speech_mcp_server/utils/responses.py:129 — [P1] Write local artifacts privately and atomically.
  • src/oci-speech-mcp-server/oracle/oci_speech_mcp_server/tools/transcription.py:468 — [P1] Preserve or clean uploaded media when job creation fails.

Additional review notes

  • [P2] Surface created notification resources after partial failure.
  • [P2] Validate model-specific transcription options.
  • [P2] Preserve actionable local I/O errors.

Validation

  • make test project=oci-speech-mcp-server passed: 45 tests and 97.21% coverage.
  • make lint and all reported GitHub checks passed. Live OCI operations were not rerun.

See the inline comments in this review for evidence, impact, and suggested remediation.

Comment thread src/oci-speech-mcp-server/oracle/oci_speech_mcp_server/utils/responses.py Outdated
Comment thread src/oci-speech-mcp-server/oracle/oci_speech_mcp_server/tools/transcription.py Outdated
Comment thread src/oci-speech-mcp-server/oracle/oci_speech_mcp_server/utils/responses.py Outdated
- write local outputs privately and atomically
- clean uploaded media when transcription job creation fails
- return structured state after partial notification or cleanup failures
- validate Oracle and Whisper model-specific options
- preserve actionable, sanitized local I/O diagnostics
- add regression tests and update documentation

@dustin-sale dustin-sale left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review by @dustin-sale via Codex.

Requested changes

  • src/oci-speech-mcp-server/oracle/oci_speech_mcp_server/tools/transcription.py:37 — [P1] Recognize supported Whisper model identifiers.
  • src/oci-speech-mcp-server/oracle/oci_speech_mcp_server/tools/transcription.py:475 — [P1] Preserve recovery state after side effects begin.

Additional review notes

  • src/oci-speech-mcp-server/oracle/oci_speech_mcp_server/__init__.py:8 — [P2] Derive the package version from distribution metadata.

Validation

  • make lint passed.
  • make test project=oci-speech-mcp-server passed with 47 tests and 96.54% coverage; all current GitHub checks also pass.

See the inline comments in this review for evidence, impact, and suggested remediation.

Comment on lines +37 to +41
known_model = model_type.strip().upper()
if known_model == "ORACLE" and whisper_prompt:
raise ValueError("whisper_prompt is supported only when model_type=WHISPER.")
if known_model == "WHISPER" and not punctuation_enabled:
raise ValueError("punctuation_enabled must be true when model_type=WHISPER.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment from @dustin-sale via Codex.

[P1] Recognize supported Whisper model identifiers

Evidence: This validation only recognizes the exact value WHISPER, but OCI SDK 2.182.1 lists WHISPER_MEDIUM and WHISPER_LARGE_V2; current OCI documentation also lists WHISPER_LARGE_V3_TURBO. A local probe showed that WHISPER_MEDIUM passes this function with punctuation_enabled=False and is then constructed with the Oracle default language_code="en-US". OCI documents locale-agnostic Whisper codes such as en and auto, and requires punctuation for Whisper. See https://docs.oracle.com/en-us/iaas/tools/python/latest/api/ai_speech/models/oci.ai_speech.models.TranscriptionModelDetails.html and https://docs.oracle.com/iaas/Content/speech/using/create-trans-job.htm.

Impact: Requests using the supported Whisper identifiers bypass the intended model-specific validation, so ordinary defaults or disabled punctuation can create asynchronously failed jobs instead of returning an immediate actionable error.

Requested change: Recognize the actual Whisper-family identifiers, enforce their language-code and punctuation rules while retaining intentional future-model extensibility, and replace the WHISPER tests with cases using at least WHISPER_MEDIUM and WHISPER_LARGE_V2.

normalization=normalization(punctuation_enabled, profanity_mode),
additional_transcription_formats=["SRT"] if include_srt else [],
)
with source.open("rb") as media:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment from @dustin-sale via Codex.

[P1] Preserve recovery state after side effects begin

Evidence: The generated Object Storage identity exists before this upload, but only a later create_transcription_job failure has special partial-state handling. An ambiguous put_object exception, or any polling, task lookup, output download, or local-write failure after job creation, reaches the outer raise_safe handler without returning the generated object name, upload location, or created job ID.

Impact: A PUT accepted before a lost response can leave sensitive media in Object Storage without a cleanup identity. A failure after job creation similarly prevents reliable resume, inspection, and cleanup, especially because display_name is not guaranteed to be unique.

Requested change: Track the workflow stage and safe partial state from before upload. On upload failure, attempt an idempotent delete or return the object identity and cleanup status. After job creation, return the upload and job identifiers with sanitized failure metadata. Add regressions for an ambiguous upload failure and a post-create download failure.

"""

__project__ = "oracle.oci-speech-mcp-server"
__version__ = "1.0.0"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment from @dustin-sale via Codex.

[P2] Derive the package version from distribution metadata

Evidence: __version__ = "1.0.0" duplicates the version in pyproject.toml. BEST_PRACTICES.md requires importlib.metadata.version(__project__), and the other Python servers in this checkout follow that pattern. The additional OCI user agent derives from this literal, while its test separately hardcodes oci-speech-mcp/1.0.0.

Impact: A future package-version bump can silently continue reporting stale OCI SDK telemetry, and the current test would still pass.

Requested change: Derive __version__ from installed distribution metadata without a fallback, and have the user-agent test derive its expected version from the same package metadata rather than another literal.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@Prabhutva we made a recent update to simplify derivation for package versions. Example:

from importlib.metadata import version as distribution_version

__project__ = "oracle.oci-speech-mcp-server"
__version__ = distribution_version(__project__)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants