Skip to content

feat: add Steam Workshop integration#28

Merged
CodeKeanu merged 6 commits into
mainfrom
feature/issue-5-workshop-integration
Dec 12, 2025
Merged

feat: add Steam Workshop integration#28
CodeKeanu merged 6 commits into
mainfrom
feature/issue-5-workshop-integration

Conversation

@CodeKeanu
Copy link
Copy Markdown
Owner

Summary

Adds Steam Workshop integration with 3 new tools for discovering, searching, and exploring mods and community content.

Changes

  • New endpoint module: src/steam_mcp/endpoints/steam_workshop.py
    • search_workshop_items - Search Workshop mods by game with text/tag filtering and sorting
    • get_workshop_item_details - Get detailed Workshop item info (description, subscribers, dependencies)
    • get_workshop_collection - Get items from a Workshop collection
  • Unit tests: 20 tests with mocked API responses in tests/test_steam_workshop.py
  • Documentation: README updated (32 → 35 tools), CHANGELOG entry added

Features

  • Text search and tag filtering support
  • Sort by popular, trending, recent, or rating
  • JSON and text output formats via supports_json=True
  • Graceful handling of games without Workshop support
  • Subscriber/favorite counts, ratings, file sizes
  • Dependencies and collection support

Testing

  • All 235 existing tests pass
  • 20 new workshop tests pass
  • Code follows existing patterns in the codebase

Checklist from Issue

  • New steam_workshop.py endpoint module with auto-discovery
  • search_workshop_items supports text search, tag filtering, and sorting
  • get_workshop_item_details returns comprehensive item information
  • get_workshop_collection returns collection contents
  • Graceful error for games without Workshop support
  • Unit tests with mocked API responses
  • Tool count updated in README (32 → 35)
  • CHANGELOG entry added

Closes #5

🤖 Generated with Claude Code

CodeKeanu and others added 2 commits December 12, 2025 12:04
Add new steam_workshop.py endpoint module with 3 tools:
- search_workshop_items: Search Workshop mods by game with text/tag filtering
- get_workshop_item_details: Get detailed Workshop item information
- get_workshop_collection: Get items from a Workshop collection

Features:
- Text search and tag filtering support
- Sort by popular, trending, recent, or rating
- JSON and text output formats
- Graceful handling of games without Workshop support
- Comprehensive error handling

Also includes:
- 20 unit tests with mocked API responses
- README updated (32 → 35 tools)
- CHANGELOG entry added

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes based on ml-python-mcp-expert review:

Must-fix:
- Filter None values from tag list comprehensions
- Add logging import and log failed batch fetches instead of silent pass
- Fix timezone-naive datetime to use UTC

Should-fix:
- Add input validation for workshop_id and collection_id
- Standardize JSON error responses (remove extra fields)
- Update endpoint description with 50-item limit note

Tests:
- Add tests for timestamp UTC formatting
- Add tests for negative timestamps
- Add input validation tests for empty/whitespace IDs
- Add test for tag filtering with missing keys

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@CodeKeanu
Copy link
Copy Markdown
Owner Author

Code Review Fixes Applied

Based on review by ml-python-mcp-expert agent, the following issues have been addressed:

Must-Fix (4 items)

  • None values in tag list comprehension - Added filter to exclude tags with missing/None tag key
  • Silent exception catch - Added logging for failed batch fetches instead of silent pass
  • Timezone-naive datetime - Changed to use UTC timezone with explicit "UTC" suffix in output
  • Added logging import - Module now imports logging and creates logger

Should-Fix (4 items)

  • Input validation - Added validation for empty/whitespace workshop_id and collection_id
  • Standardized JSON errors - Removed extra fields from empty search results error response
  • 50-item limit documentation - Added note to get_workshop_collection description
  • Negative timestamp handling - Changed ts == 0 to ts <= 0 check

New Tests Added

  • test_format_timestamp_negative - Validates negative timestamps return "Unknown"
  • test_empty_workshop_id_returns_error - Validates empty workshop_id validation
  • test_whitespace_workshop_id_returns_error - Validates whitespace-only input
  • test_empty_workshop_id_json_format - Validates JSON error response for validation
  • test_empty_collection_id_returns_error - Validates empty collection_id validation
  • test_whitespace_collection_id_returns_error - Validates whitespace-only input
  • test_tags_with_missing_key_filtered - Validates None tag filtering

All 242 tests pass ✅

The Steam API can return numeric fields as strings (e.g., "1000" instead
of 1000). This caused TypeError: '<' not supported between 'str' and 'int'.

Fixes:
- Add _safe_int() helper for int coercion with default fallback
- Add _safe_float() helper for float coercion with default fallback
- Update _format_file_size() to handle string/None inputs
- Update _format_timestamp() to handle string/None inputs
- Apply _safe_int/_safe_float to all numeric API fields:
  - subscriptions, favorited, views, file_size
  - vote_data.score, votes_up, votes_down
  - result, file_type comparisons
  - time_created, time_updated

Tests:
- Add TestStringTypeCoercion class with 7 tests
- Tests cover string values in search, details, and collection endpoints
- Tests for _safe_int, _safe_float, and format functions with string input

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@CodeKeanu
Copy link
Copy Markdown
Owner Author

Type Safety Fixes Applied

Fixed the TypeError: '<' not supported between instances of 'str' and 'int' error.

Root Cause

The Steam API can return numeric fields as strings (e.g., "1000" instead of 1000). Our mock tests used proper int types, so this wasn't caught during unit testing.

Solution

Added type coercion helpers and applied them throughout:

Helper Purpose
_safe_int(value, default=0) Safely convert to int, handles str/None
_safe_float(value, default=0.0) Safely convert to float, handles str/None

Fields Updated

  • subscriptions, favorited, views, file_size
  • vote_data.score, votes_up, votes_down
  • result, file_type (for comparisons)
  • time_created, time_updated
  • _format_file_size() and _format_timestamp() now accept string inputs

New Tests Added (7 tests)

  • test_search_handles_string_numeric_values - API returns strings for numeric fields
  • test_item_details_handles_string_values - Details endpoint with string values
  • test_collection_handles_string_values - Collection endpoint with string values
  • test_safe_int_function - Unit test for _safe_int
  • test_safe_float_function - Unit test for _safe_float
  • test_format_file_size_string_input - String input handling
  • test_format_timestamp_string_input - String input handling

All 249 tests pass

@CodeKeanu
Copy link
Copy Markdown
Owner Author

It is able to sort through individual workshop items correctly and all the user to filter however they want. However, the collections feature is flawed, the user currently needs to know the id of the collection in question, there is no way for the user to be able to just get the top 5 most popular collections. The collection endpoint needs to have sorting and filtering similar to that of the "search workshop items" tool. In its current state, its not very user-friendly

CodeKeanu and others added 3 commits December 12, 2025 20:30
Users previously needed to know collection IDs upfront. The new
search_workshop_collections tool lets users browse and discover
collections with the same sorting/filtering options as search_workshop_items:
- Sort by popular, trending, recent, or rating
- Text search support
- Returns collection name, item count, subscriber count

Also updated get_workshop_collection description to reference the
new discovery tool.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Brings search_workshop_collections to feature parity with
search_workshop_items - both now support:
- app_id (required)
- search_query (text search)
- tags (array of Workshop tags to filter by)
- sort_by (popular/trend/recent/rating)
- max_results

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Was using filetype=2 (Artwork) instead of filetype=1 (Collections).
Per Steamworks API docs, EPublishedFileInfoMatchingFileType values:
- 0 = Items (regular mods)
- 1 = Collections
- 2 = Art
- 3 = Videos

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@CodeKeanu CodeKeanu merged commit 1958af2 into main Dec 12, 2025
3 checks passed
@CodeKeanu CodeKeanu deleted the feature/issue-5-workshop-integration branch December 12, 2025 20:56
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.

Feature: Steam Workshop Integration

1 participant